“合并分支”“开发”和“合并分支”有什么区别?进入功能/tmp”和“合并分支‘开发’” https://github.com/~ 进入 feature/tmp”?

发布于 2025-01-10 16:17:11 字数 159 浏览 0 评论 0原文

我看到两条合并提交消息 Mergebranch 'develop' into feature/tmpMergebranch 'develop' of https://github.com/~ into feature/tmp。他们之间有什么区别?

I saw two merge commit message Merge branch 'develop' into feature/tmp and Merge branch 'develop' of https://github.com/~ into feature/tmp. What is difference between them?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

笑着哭最痛 2025-01-17 16:17:11

正如其他人在评论中已经说过的那样,您在这里看到的消息只是文本。任何人都可以创建他们喜欢的任何文本。但这两条消息是某些 Git 命令的默认文本。要理解这一点,您必须了解 Git 和提交。

Git 存储库由两个数据库组成:

  • 一个数据库保存提交,另一个数据库保存其他内部 Git 对象。
  • 另一个数据库保存名称:分支名称、标签名称和其他名称。这些名称可以帮助您(和 Git)找到您关心的提交

所有 Git 内部对象都是严格只读的,并且在大多数情况下,对象数据库只是您添加的对象。这就是 Git 恢复之前版本的方式:之前的版本位于之前的提交中。您进行新的提交,这会添加新版本。提交历史记录。1

提交(以及其他内部对象)都有哈希 ID。任何给定提交的哈希 ID 在每个 Git 存储库中都是完全唯一。这意味着两个不同的克隆(或者实际上是任何两个存储库)可以轻松区分它们与其他克隆的差异:它们共享或共同的提交始终具有相同的内容 哈希 ID。对于他们共享的提交,一个Git会找到一些哈希IDa123456...或其他什么,而另一个Git不会在找到任何对象全部具有该哈希 ID。

对于您(使用 Git 的人)来说,这意味着哈希 ID 就是提交,具有非常真实且重要的意义。但哈希 ID 的问题是:它们又大又丑,没有人可以直接使用它们。所以我们不这样做:我们使用分支名称来查找提交。这就是第二个数据库的用武之地。


1此历史记录实际上无法更改。当您看到人们谈论“重写历史”时,他们的意思是您添加了新历史,并且新历史不会引用旧的提交(现有历史)。通常,您添加的新历史记录确实会引用旧历史记录。在一对 Git 存储库数据库中,您可以并且确实可以更改的是存储在名称中的值。如果名称 main 让您今天找到提交 a123456,明天提交 b789abc,那么“history”就是您可以通过启动找到的提交集今天在 a123456 处,明天从 b789abc 处开始可以找到一组提交。通常,我们安排b789abc引用回a123456;为了“重写历史记录”,我们根据需要复制尽可能多的原始历史记录到新的和改进的提交,添加我们喜欢的任何其他仅限新的提交,并使 b789abc 引用新的历史记录而不是古老的历史。

此时,旧的历史并没有消失。您只是无法再看到它了。最终,Git 将清理这些完全不可见的提交,前提是 (a) 它们完全不可见,并且 (b) 您不会返回并改变主意并使它们再次可见。


分支名称查找提交

分支名称与提交不同,不是唯一的。您的 Git 存储库中可能有一个 mainmaster,我的 Git 存储库中可能也有一个,这两个名称将保存不同提交哈希值身份证。对于任何名称(包括标签名称)都可能如此,但如果我们的两个存储库克隆,我们应该在标签中存储相同的哈希ID名称。 (否则完全可能,但会导致疯狂,或者至少,混乱。不要这样做。)

因为分支名称的定义是它保存最新提交的哈希ID,但是,我们期望不同克隆中的分支名称会随着时间的推移而变化。每次您签出某个分支并进行一些新的提交时,您都会更新您的分支名称的哈希 ID。哈希 ID 查找最新提交。最新提交具有每个提交所具有的内容:

  • 提交保存所有源文件的快照,例如 tar 或 rar 或 winzip 存档。 (但是,所包含文件的格式很奇怪并且是特定于 Git 的,这些文件实际上是在提交内和提交之间共享/重用的。这意味着如果您进行新的提交,其中只有一个文件更改,Git 重新使用新快照中除更改的文件之外的所有文件,因此几乎不占用空间。)

  • 一次提交保存< em>元数据,或有关提交本身的信息。例如,这包括提交人的姓名和电子邮件地址。它包括一些日期和时间戳。而且,为了让历史记录在 Git 中发挥作用,它包含先前提交的哈希 ID 列表。

大多数提交在其元数据中准确记录了一个先前的提交哈希 ID。这会产生一个简单的向后看的提交链:这就是该分支中的历史记录。 分支名称提供最新提交的原始哈希ID。该最新提交提供了所有文件的快照,以及第二个最新提交的哈希ID。第二个最新提交提供了所有文件的快照,加上第三个最新提交的哈希 ID,其中包含快照和元数据,提供了第四个最新提交的哈希 ID,其中包含快照和元数据......好吧,您现在可能明白了:

... <-F <-G <-H   <--main

如果 main 是我们的分支名称,并且它保存的哈希 ID 是一些大而难看的随机字符串,我们简称为 H,然后名称 main 点提交H。提交H在其元数据中存储了先前提交G的哈希ID(即指向)。提交G 存储更早提交F 的哈希ID,依此类推。

这就是存储库中的历史记录。我们使用分支名称来查找最新提交,然后 Git 为我们反向工作。这就是全部,但这就是我们所需要的

合并

当我们有几个具有共同历史和各自历史的分支时,如下所示:

          I--J   <-- br1
         /
...--G--H
         \
          K--L   <-- br2

我们可以要求 Git 合并 提交 JL,通过 这样做:

git switch br1 && git merge br2

也就是说,我们首先选择提交 J 作为我们的当前提交,并选择分支名称 br1 作为我们的当前分支嗯>。然后我们告诉 Git:使用名称 b2,查找提交并合并。该名称现在定位提交 L,因此 Git 使用提交JL 来确定分支之前同步的时间,并执行一些操作简单而愚蠢的面向文本的东西来结合工作在两个分支中完成。

这种组合工作的结果是一个新快照。这个新快照进入新提交,我们在这里将其称为M。新提交以通常的方式进入当前分支:新提交在其元数据中存储当前提交的哈希ID,以便M< /code> 指向 J

          I--J
         /    \
...--G--H      M
         \
          K--L

合并提交 M 的特殊之处在于,在其元数据中,它列出了两个提交哈希 ID,而不仅仅是一。列表中的第二哈希ID是我们合并的提交的哈希ID,即提交L

          I--J
         /    \
...--G--H      M   <-- br1 (HEAD)
         \    /
          K--L   <-- br2

Git更新的分支名称,在我们的存储库是 br1,因为这是我们在运行 git merge 之前为 git checkout 或 git switch 指定的分支名称代码>.括号中的名称 HEAD 附加到其中一个分支名称,是显示当前分支名称的一种方式。 当前提交是当前分支名称指向的提交。现在我们已经进行了新的提交 M,Git 已更新 br1,因此 M 现在是分支 br1 上的最新提交

因为M向后指向两者JL全部< /em> 提交现在位于分支 br1 上。因为 br2 指向 L,并且从 L 向后工作找不到提交 MI< /code> 或 J,此时 br1 上有 3 个提交不在 br2 上。

远程和远程跟踪名称

Git 不仅仅是一个版本控制系统或VCS,而是一个分布式 VCS。在 Git 的例子中,这是通过克隆实现的。我们克隆一个存储库,当我们这样做时,我们会得到其他存储库的所有提交,并且没有任何分支

也就是说,假设某个other存储库有一个main和一个develop

...--F--G--H   <-- main
         \
          I--J   <-- develop

我们运行git clone url。我们的 Git:

  • 以 Git 调用远程的名称保存 URL;
  • 创建一个新的、完全空的存储库:两个数据库都是空的;
  • 连接到响应给定 URL 的任何人:这应该是某个 Git 软件,连接到 Git 存储库,我们将该组合称为“他们的 Git”;
  • 从他们的 Git 中获取所有分支名称的列表以及相应的提交哈希 ID;
  • 使用这些哈希 ID 来获取他们的提交,包括他们的历史记录(所有早期提交);
  • 获取所有分支名称并重命名,并在我们存储库中创建重命名名称。

为了构建新名称,我们的 Git 软件会采用它们的分支名称并将远程名称放在前面。标准的第一个远程名称是origin。因此,远程 origin 为我们做了两件事:

  • 保存 URL,以便我们将来可以随时再次联系他们的 Git;它
  • 提供了远程跟踪名称前缀:他们的main成为我们的origin/main,他们的develop成为我们的起源/发展

这些远程跟踪名称的功能类似于分支名称 - 它们找到最新提交 - 但它们实际上并不是分支名称。我们无法git switch到它们。所以现在我们的存储库中有这个:

...--F--G--H   <-- origin/main
         \
          I--J   <-- origin/develop

但从某种意义上说,我们自己的 Git 软件想要“在分支上”。为了进入一个分支,我们的 Git 现在必须创建一个分支名称。我们的 Git 将创建什么分支名称?答案分为两部分:

  1. 我们的 Git 将在命令行上使用 -b 选项创建我们告诉它的分支名称。
  2. 如果我们没有使用 -b(而且我们也没有使用),我们的 Git 会询问他们的 Git 他们推荐哪个名称。此处可能是 maindevelop,因为它们是它们拥有的两个分支名称。他们推荐 main 是很典型的。

因此,考虑到所有这些,我们的 Git 现在可能会创建 main 。我们的名称 main 将指向哪个提交?答案是:现在,他们的名称所指向的提交相同,我们已将其以名称 origin/main 存储在本地。所以我们得到:

...--F--G--H   <-- main (HEAD), origin/main
         \
          I--J   <-- origin/develop

请注意,我们现在有两个名称指向提交H。没关系!一次提交可以有任意多个名称。每个名称要么是一个分支名称(例如此处的main),要么是某种其他类型的名称(例如此处的远程跟踪名称)。 分支名称是我们可以给git switch的名称,以“进入”分支,之后我们所做的任何提交都会前进指向新提交的分支名称,它将指向当时最新的提交。因此,如果我们坚持使用 main 并进行新的提交,我们会得到:

             K   <-- main (HEAD)
            /
...--F--G--H   <-- origin/main
         \
          I--J   <-- origin/develop

本地合并与 git pull

要进行纯粹的本地合并,我们:

  • 按名称切换到某个分支,然后
  • 运行 ​​git merge 并为合并命令提供分支名称或任何其他方式来查找任何提交。

只要其他提交是 Git 可以合并的内容,Git 就会进行合并(或者不进行合并 - 例如,git merge 有选项使其执行常规合并以外的操作,并且有一些默认值)并不总是合并的操作 - 但我们在这里假设我们得到了真正的合并)。新的合并提交是一个提交,因此它具有快照和元数据。元数据包括日志消息

当您运行 git merge 且 Git 进行新合并时,Git 默认情况下会在带有合并消息的文件上打开编辑器。合并消息是您告诉人们为什么执行此 git merge 命令的地方。不过,大多数人都不会打扰。他们只是让 Git 使用其蹩脚的默认合并消息。 默认合并消息是:

Merge branch 'develop'

或:

Merge branch 'develop' into feature/tmp

左侧单引号中的名称,在本例中为 'develop',是我们为 git 指定的名称合并命令。当我们位于名为 feature/tmp 的分支时,into feature/tmp 部分就会出现;如果我们不在 main 分支上,则默认显示 into 部分,无论它是什么(mastermain,现在是可配置的;在旧版本的 Git 中,master 是唯一这样被省略的)。

这条默认消息不太好。它如此乏味的原因是分支名称​​随着时间的推移而变化,以指向新的提交。如果您感觉精力充沛,您可以将其更改为,例如:

Merge Bob's update to incorporate the new foobler software,
because our feature development needs to foo some bars.

然而,实际上,正如我之前所说,似乎没有人打扰。 (您或进行此合并的任何人显然也没有打扰。)

现在,如果您在 feature/tmpgit mergedevelop ,就会发生这种情况>。但是如果你运行:

git pull origin develop

?在本例中,您使用的是 git pull 便捷命令。该命令是运行两个 Git 命令的缩写:

  1. git fetch;然后
  2. 是您选择的命令,通常配置一次,然后从现在开始使用。

步骤 2 中的默认命令是 git merge。这似乎是您的设置:默认设置,即您从未将 git pull 配置为运行不同的东西。 (有些团体更喜欢使用 rebase 而不是 merge,但这是个人喜好问题:偏好 rebase 有有效的论据,也有偏好合并的有效论据。Git 默认为 merge,这至少简单 rebase。)

每当您直接运行 git fetch 或通过 git pull 运行时,您的 Git 都会连接到另一个 Git(该软件在保存的 URL 上进行响应,使用保存的存储库指示网址)。您的 Git 从他们的 Git 获取您没有但需要的任何新提交2 然后,您的 Git 会更新您的 origin/在您自己的存储库中开发3因此,如果您有,请说:

       J--K   <-- feature/tmp (HEAD)
      /
...--H   <-- main
      \
       I   <-- origin/develop

git fetch 步骤之前,以及:

       J--K   <-- feature/tmp (HEAD)
      /
...--H   <-- main
      \
       I--L   <-- origin/develop

git fetch 之后> git pull 的步骤,这意味着他们自上次 git fetch 以来,向他们的存储库添加了一个提交(我们在此称为 L 的提交)。现在,您的存储库中也有该提交,并且您的 origin/develop 现在指向该特定提交。

您的 Git 软件现在运行命令二,以完成 git pull。在本例中,第二个命令是 git merge,因此您的 Git 会进行常规合并,这会生成一个新的合并提交 M:(

       J--K
      /    \
...--H      M   <-- feature/tmp (HEAD)
      \    /
       I--L   <-- origin/develop

我停止在名称中绘制 main,但它仍然在那里,指向提交 H:现在很难绘制)。

新的合并提交M在其元数据中有一条日志消息。与您可能亲自运行的git merge命令一样,Git通常会给您一个机会编辑此日志消息并添加更好的内容,但 Git 提供了一个蹩脚的默认值。不过,默认值不是来自 git merge,而是来自 git pull。 git pull 命令知道您刚刚从通过名称 存储的 URL 获取了最新 develop起源。因此,您的 git pull 会生成默认的相当蹩脚的日志消息:

Merge branch 'develop' of <url> into feature/tmp

部分是来自 origin 的部分; develop 是您给 git pull 的参数,即提交他们的 Git 的 develop 已识别,通过 git fetch 传输 - 如果您不在主分支上,则像往常一样添加 into 部分,而您不在主分支上。

您(或进行此合并的任何人)接受了这个不太好的默认提交消息(就像大多数人所做的那样),所以这就是您得到它的方式。


2当您不带任何参数运行 git fetch 时,您的 Git 会从其 Git 所有分支获取并创建或更新以通常的方式列出您的所有远程跟踪名称。您可以告诉git fetch将其获取的内容限制一个分支所需的内容,并且git pull有时会做这个。在这种特殊情况下,git pull origindevelop 指示 git fetch 带来新的 develop 提交,然后仅更新您自己的 起源/发展

3Git 1.8.4 之前的 Git 版本无法在这些有限获取的情况下更新远程跟踪名称。要解决这个问题,请确保您没有使用旧版本的 Git。


底线

无论谁通过运行 git merge 在本地进行合并,都让 Git 使用其默认合并消息。

无论是谁通过运行 git pull 在本地进行合并,都让 Git 使用其默认合并消息。

由于分支名称总是在演变,因此这两条消息都没有多大价值。 pull 消息确实告诉您,无论是谁执行此操作,都使用特定的 GitHub 克隆作为他们合并的提交的源。这些信息是否有任何价值可能只能根据个人情况来回答。

As others already said in comments, the message you see here is just text. Anyone can create any text they like. But these two messages are the default text for certain Git commands. To understand this, you must understand Git and commits.

A Git repository consists of two databases:

  • One database holds commits, and other internal Git objects.
  • The other database holds names: branch names, tag names, and other names. These names help you (and Git) find the commits you care about.

All Git internal objects are strictly read-only, and for the most part, the object database is something you only ever add to. That's how Git can get any of your previous versions back: the previous versions are in previous commits. You make new commits, and that adds new versions. The commits are the history.1

The commits (and the other internal objects) all have hash IDs. The hash ID of any given commit is totally unique, across every Git repository. This means that two different clones (or any two repositories, in fact) can easily tell where they diverge from some other clone: the commits they share, or have in common, always have the same hash ID. For commits they don't share, one Git will find some hash ID a123456... or whatever, and the other Git won't find any object at all with that hash ID.

What this means for you, a person using Git, is that the hash ID is the commit, in a very real and important sense. But the problem with hash IDs is: they're huge and ugly and no human can use them directly. So we don't: we use branch names to find commits. That's where the second database comes in.


1This history cannot actually be changed. When you see people talk about "rewriting history", what they mean is that you've added new history, and the new history doesn't refer back to the old commits—the existing history. Normally, you add new history that does refer back to the old history. What you can and do change in a pair of Git repository databases are the values stored in the names. If name main lets you find commit a123456 today, and commit b789abc tomorrow, then "history" is the set of commits you can find by starting at a123456 today, and the set of commits you can find by starting at b789abc tomorrow. Normally, we arrange for b789abc to refer back to a123456; to "rewrite history", we copy as much original history as needed to new-and-improved commits, add any other new-only commits we like, and make b789abc refer back to the new history instead of the old history.

The old history doesn't go away, at this point. You just can't see it any more. Eventually, Git will get around to cleaning out these completely-invisible commits, provided that (a) they are completely invisible and (b) you don't go back and change your mind and make them visible again.


Branch names find commits

Branch names, unlike commits, aren't unique. You might have a main or master in your Git repository, and I might have one in mine, and these two names will hold different commit hash IDs. That's potentially true for any name, including tag names, but if our two repositories are clones, we should store the same hash IDs in our tag names. (To do otherwise is perfectly possible, but leads to insanity, or at least, confusion. Don't do that.)

Because the definition of a branch name is that it holds the hash ID of the latest commit, though, we expect the branch names in different clones to vary over time. Every time you check out some branch and make some new commit(s), you're updating your branch name's hash ID. The hash ID finds the latest commit. The latest commit has what every commit has:

  • A commit holds a snapshot of all the source files, like a tar or rar or winzip archive. (However, the format of the contained files is weird and Git-specific, with the files literally being shared / re-used within and across commits. This means if you make a new commit where only one file is changed, Git re-uses all the files except the one changed one, in the new snapshot, which therefore takes almost no space.)

  • A commit holds metadata, or information about the commit itself. This includes the name and email address of the person who made the commit, for instance. It includes some date-and-time-stamps. And, so that history works in Git, it includes a list of hash IDs of previous commits.

Most commits record exactly one previous commit hash ID here, in their metadata. This produces a simple backwards-looking chain of commits: that's the history in this branch. The branch name provides the raw hash ID of the latest commit. That latest commit provides the snapshot of all files, plus the hash ID of the second-latest commit. That second-latest commit provide the snapshot of all files, plus the hash ID of the third-latest commit, which has a snapshot and metadata giving the hash ID of the fourth-latest commit, which has a snapshot and metadata ... well, you probably get the picture now:

... <-F <-G <-H   <--main

If main is our branch name and the hash ID it holds is some big ugly random-looking string that we just call H for short, then the name main points to commit H. Commit H, in its metadata, stores the hash ID of—i.e., points to—earlier commit G. Commit G stores the hash ID of still-earlier commit F, and so on.

That's the history in the repository. We use the branch names to find the latest commits and then Git works backwards for us. That's all there is, but that's all we need.

Merging

When we have several branches with both common and their own history, like this:

          I--J   <-- br1
         /
...--G--H
         \
          K--L   <-- br2

we can ask Git to merge commits J and L, by doing:

git switch br1 && git merge br2

That is, we start by selecting commit J as our current commit, and branch name br1 as our current branch. Then we tell Git: Using the name b2, find the commit, and merge. That name locates commit L right now, so Git uses commits J and L to figure out when—at which commit—the branches were in sync before, and does some simple and stupid text-oriented things to combine the work done in the two branches.

The result of this combining-work is a new snapshot. This new snapshot goes into a new commit, which we'll call M here. The new commit goes onto the current branch in the usual way: the new commit stores, in its metadata, the hash ID of the current commit so that M points back to J:

          I--J
         /    \
...--G--H      M
         \
          K--L

What's special about merge commit M is that in its metadata, it lists two commit hash IDs instead of just one. The second hash ID in the list is that of the commit we merged in, i.e., commit L:

          I--J
         /    \
...--G--H      M   <-- br1 (HEAD)
         \    /
          K--L   <-- br2

The branch name that Git updates, in our repository, is br1, because that's the branch name we gave to git checkout or git switch before we ran git merge. The name HEAD in parentheses, attached to one of the branch names, is a way to show the current branch name. The current commit is the one the current branch name points-to. So now that we've made new commit M, Git has updated br1 so that M is now the latest commit on branch br1.

Because M points backwards to both J and L, all the commits are now on branch br1. Because br2 points to L, and working backwards from L does not find commits M, I, or J, there are three commits on br1 that are not on br2, at this point.

Remotes and remote-tracking names

Git is not merely a version control system or VCS, but is a distributed VCS. In Git's case, this is implemented via clones. We clone a repository, and when we do, we get all of the other repository's commits, and none of its branches.

That is, suppose some other repository has a main and a develop:

...--F--G--H   <-- main
         \
          I--J   <-- develop

We run git clone url. Our Git:

  • saves away the URL, under a name Git calls a remote;
  • creates a new, totally-empty repository: both databases are empty;
  • connects to whoever responds to the given URL: that should be some Git software, connected to a Git repository, and we'll call that combination their Git;
  • obtains from their Git a list of all their branch names and the corresponding commit hash IDs;
  • uses those hash IDs to get those commits from them, including their history (all earlier commits);
  • takes all their branch names and renames them, and creates in our repository the renamed names.

To build the new names, our Git software takes their branch names and sticks the remote's name in front. The standard first remote name is origin. So the remote, origin, does two things for us:

  • it saves the URL, so that we can contact their Git again any time in the future; and
  • it provides the remote-tracking names prefix: their main becomes our origin/main, and their develop becomes our origin/develop.

These remote-tracking names function like branch names—they find the latest commit—but they are not actually branch names. We cannot git switch to them. So now we have this, in our repository:

...--F--G--H   <-- origin/main
         \
          I--J   <-- origin/develop

But our own Git software wants, in some sense, to be "on a branch". To be on a branch, our Git must now create one branch name. What branch name will our Git create? The answer comes in two parts:

  1. Our Git will create the branch name we told it to, on the command line, using the -b option.
  2. If we didn't use -b—and we didn't—our Git asks their Git which name they recommend. That could be either main or develop here, since those are the two branch names they have. It's pretty typical for them to recommend main.

So, with all that in mind, our Git probably creates main now. Which commit will our name main point-to? The answer is: the same commit their name points to, right now, which we've stored locally with the name origin/main. So we get:

...--F--G--H   <-- main (HEAD), origin/main
         \
          I--J   <-- origin/develop

Note that we now have two names pointing to commit H. That's fine! A commit can have as many names as you want. Each name is either a branch name, like main here, or some other kind of name, like the remote-tracking names here. Branch names are the ones we can give to git switch, to get "on" the branch, after which any new commits we make will advance the branch name to point to the new commit, which will point back to whatever commit was the latest, at that time. So if we stick with main and make a new commit, we get:

             K   <-- main (HEAD)
            /
...--F--G--H   <-- origin/main
         \
          I--J   <-- origin/develop

Merging locally vs git pull

To do a purely local merge, we:

  • switch to some branch by name, then
  • run git merge and give the merge command a branch name or any other way to find any commit.

As long as the other commit is something Git can merge, Git will do the merge (or not—git merge has options to make it do something other than a regular merge, for instance, and has some default actions that don't always merge—but we'll assume here that we get a real merge). The new merge commit is a commit, so it has a snapshot and metadata. The metadata include a log message.

When you run git merge and Git makes a new merge, Git will, by default, open your editor on a file with a merge message. The merge message is where you tell people why you did this git merge command. Most people don't bother, though. They just let Git use its crappy default merge message. That default merge message is:

Merge branch 'develop'

or:

Merge branch 'develop' into feature/tmp

The name on the left and in single quotes, 'develop' in this case, is the name we gave to the git merge command. The into feature/tmp part appears when we're on a branch named feature/tmp; the into part appears by default if we're not on the main branch, whatever that is (master or main, now configurable; in older versions of Git, master was the only one that got omitted like this).

This default message is not very good. The reason it's so blah is that branch names change over time, to point to new commits. If you're feeling extra-energetic, you might change it to, e.g.:

Merge Bob's update to incorporate the new foobler software,
because our feature development needs to foo some bars.

In practice, however, nobody seems to bother, as I said earlier. (You, or whoever made this merge, apparently didn't bother either.)

Now, that's what happens if you run git merge develop when you're on your feature/tmp. But what if you run:

git pull origin develop

? In this case you're using the git pull convenience command. This command is short for running two Git commands:

  1. git fetch; then
  2. a command of your choice, that you'd normally configure once and then use from now on.

The default command in step 2 is git merge. That seems to be your setup: the default, i.e., you never configured git pull to run something different. (Some groups prefer to rebase instead of merge, but that's a personal preference thing: there are valid arguments for preferring rebase, and valid arguments for preferring merge. Git defaults to merge, which is at least simpler than rebase.)

Whenever you run git fetch—either directly, or via git pull—your Git reaches out to the other Git (the software that responds at the saved URL, using the repository indicated by the saved URL). Your Git gets, from their Git, any new commits they have that you don't, that you'll need.2 Your Git then updates your origin/develop in your own repository.3 So if you had, say:

       J--K   <-- feature/tmp (HEAD)
      /
...--H   <-- main
      \
       I   <-- origin/develop

before the git fetch step, and:

       J--K   <-- feature/tmp (HEAD)
      /
...--H   <-- main
      \
       I--L   <-- origin/develop

after the git fetch step of git pull, that means they added one commit—the one we're calling L here—to their repository since your last git fetch. You now have that commit in your repository too, and your origin/develop now points to that particular commit.

Your Git software now runs command-number-two, to complete the git pull. That second command in this case is git merge, so your Git does a regular merge, which produces a new merge commit M:

       J--K
      /    \
...--H      M   <-- feature/tmp (HEAD)
      \    /
       I--L   <-- origin/develop

(I stopped drawing in the name main, but it's still there, pointing to commit H: it's just too hard to draw now).

New merge commit M has a log message in its metadata. As with a git merge command you might run personally, Git normally gives you a chance to edit this log message and put in something better, but Git provides a crappy default. The default comes not from git merge, though, but this time from git pull. The git pull command knows that you just got the latest develop from the URL stored via the name origin. So your git pull generates, as its default fairly-crappy log message:

Merge branch 'develop' of <url> into feature/tmp

The <url> part is the one from origin; the develop is the argument you gave to git pull—that is, the commit their Git's develop identified, as transferred over via git fetch—and the into part is as usual added if you're not on your main branch, which you're not.

You—or whoever did this merge—accepted this not-so-great default commit message (as most people mostly do), so that's how you got it.


2When you run git fetch with no arguments at all, your Git gets from their Git all of their branches and creates or updates all your remote-tracking names in the usual way. You can tell git fetch to limit what it fetches to that needed for one branch, and git pull will sometimes do this. In this particular case, git pull origin develop instructs git fetch to bring over their new develop commits, and then updates only your own origin/develop.

3Git versions predating Git 1.8.4 fail to update remote-tracking names in these limited-fetch cases. To fix that, make sure you're not using an ancient version of Git.


The bottom line

Whoever made one merge locally by running git merge let Git use its default merge message.

Whoever made one merge locally by running git pull let Git use its default merge message.

Since branch names are always evolving, neither message has much value. The pull message does tell you that whoever did it was using that particular GitHub clone as the source for the commits they merged. Whether that information has any value at all is probably only answerable on an individual basis.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文