为什么Git merge命令给了我不同的ouptut

时间:2015-08-03 11:21:09

标签: git git-merge

我和Git已经合作了一年了,今天在合并分支机构时偶然发现了令人困惑的事情。这是我本地的.config文件部分:

[branch "develop"]
    remote = origin
    merge = refs/heads/develop

[branch "Feature/Sprint4.4/mybranch"]
    remote = origin
    merge = refs/heads/Feature/Sprint4.4/mybranch

现在我在当地分支mybranch。我按顺序执行了以下命令。

1) git pull
 --> 2d6cf1e..655001e  develop    -> origin/develop
 --> already up-to-date
2) git merge origin develop
 --> already up-to-date
3) git merge origin/develop
 --> merge made by recursive strategy...
     ....(all the changes were indicated)
      7 files changed, 202 insertions(+), 181 deletions(-)

我的问题是上面的命令(2)和(3)之间的确切区别是什么以及输出改变的原因?

我知道我可以通过Git文档和其他书籍,但寻找答案更简单的语言。

2 个答案:

答案 0 :(得分:1)

您在mybranch

1) git pull  // This will pull changes from origin and write them into your my branch.(It will fetch for your develop branch)
 --> 2d6cf1e..655001e  develop    -> origin/develop
 --> already up-to-date
2) git merge origin develop  // This will take almost no effect as you already pulled as it shows develop -> origin/develop
                            // This is same as git merge origin/develop develop
 --> already up-to-date
3) git merge origin/develop  // This will merge changes from origin/develop to mybranch
                             // This is same as git merge origin/develop mybranch
 --> merge made by recursive strategy...
     ....(all the changes were indicated)
      7 files changed, 202 insertions(+), 181 deletions(-)

答案 1 :(得分:1)

我知道这已经得到了回答和接受,但我认为接受的答案中缺少一点关键。

您几乎不希望使用超过一个附加参数运行git merge

换句话说,git merge origin develop很少是一个好主意;不要这样做。要了解原因,请继续阅读。

git pullgit merge采用不同的参数

git pull仅运行git fetch后跟git merge(或者,如果您指示git pull,那么这是正确的(即,它是正确的){{1}然后是git rebase)。棘手的部分是如何运行它们,pull命令通常需要两个参数:

$ git pull remote refspec

merge命令通常需要一个

$ git merge commit

请注意此处的名称( remote refspec commit )都不同:这是理解命令的关键之一。另外,请注意"一般"在谈论所使用的参数数量时:有时可能会省略某些参数,或者使用更多的参数。

什么是"远程"?

在最简单的形式中,远程只是一个名为origin的名称,它引用git配置文件(.git/config)中的条目。 pull脚本有很长的使用它的替代方法的历史,所以你可以把其他的东西放在这里,但只要你只使用这些名字,事情就会很好用而且不那么令人困惑,所以让我们来看看。把它留在那。

什么是" refspec"?

完整的refspec最多有三个部分。这三个问题对git push很重要,但git fetch更不重要,而且git pull运行git fetch,我们可以使用最简单的版本,它只是一个分支或标记名称。使用git fetch(以及git pull)时,您提供的分支名称是远程上的分支的名称。因此:

git pull origin branch

让你的git联系远程origin并询问它名为 branch 的分支。

假设分支机构名称存在于遥控器上,你的git将获得该分支的最新版本(通常也会更新refs/remotes/origin/branch,至少如果你有git版本1.8.4或更新版本是的,对于更新版本的git,您的"远程跟踪分支"总是得到更新。)

作为git pull依赖的副作用,git fetch 将所有更新的分支信息 1 写入名为{{1的文件在git的私有(FETCH_HEAD)目录中。您真正需要知道的唯一事情是.git脚本使用它(但如果您愿意,可以阅读文件的内容)。

到目前为止

摘要:pull运行git pull并将更新存储在git fetch 中,有时也存储在您的远程跟踪分支中#34} ;例如FETCH_HEADorigin/master等等。

使用origin/develop

现在让我们转到git merge

我上面说过它"一般"有三个参数,git merge

git merge commit命令始终给出pull三个参数(以及许多标志,包括一些用于提供合并提交消息的标志)。 merge脚本获取 commit 参数 - 就此而言,pull文件的合并提交消息 - 2

如果你想手动执行此操作,可以像FETCH_HEAD脚本那样执行此操作,但提取和输入长SHA-1 ID非常痛苦。而且,在任何情况下,您要做的是合并一个不同的本地分支,而不是pull步骤带来的提交的原始SHA-1。

您输入命令时最初出错的地方:

fetch

这会将两个参数传递给git merge origin develop 。它们都被视为提交ID,这告诉merge执行一个名为" octopus merge"的事情。除非你是一名高级的git master,否则你可能不想这样做。 (幸运的是,在你的情况下,考虑到你给git的多个提交ID,无论如何都无事可做。)

我会在此注意git merge 看起来像是提交ID,origin也不像SHA-1。但事实上,这两个名称​​做都指定了特定的提交 - 如果他们没有,你会从develop命令得到一条错误消息。要查找哪些提交,您可以使用命令git merge

git rev-parse

(你的胜利与这个SHA-1不相符,但这个想法应该足够明确了)。分支名称也解析为原始SHA-1 - 我没有$ git rev-parse origin a17c56c056d5fea0843b429132904c429a900229 但我确实有developmaster所以我会在这里使用这些:

origin/master

(在这种情况下,两者与我的$ git rev-parse master a17c56c056d5fea0843b429132904c429a900229 $ git rev-parse origin/master a17c56c056d5fea0843b429132904c429a900229 相同,现在与master最新。)

通常,分支名称解析为分支顶端的提交。

我会重复这一点,因为它是理解git的另一个关键。 分支名称解析为分支顶端的提交,其中包含一个非常重要且非常重要的异常,即执行origin/master时。由于git checkout是人们使用git做的第一件事之一,他们知道分支名称是特殊的 - 这对于git checkout是正确的,但对于大多数其他git命令则不然。大多数命令只是将名称转换为原始SHA-1,当它们执行时,它们会获得分支的提示。

git checkout

使用符号名称git merge origin/develop 运行git merge非常合理:git会为您查找原始提交ID,并设置默认合并消息以使用符号名称,这对于人类稍后阅读日志意味着更多。如果您使用原始提交ID,那么您将在日志中获得该ID。

合并摘要: origin/develop是合理的做法。这意味着"找到git merge origin/develop的提示提交并将其合并为常规合并。"但是,origin/develop 是一个好主意,因为它意味着"找到git merge origin developorigin的提示提交并执行这两个章节的合并提交"

1 当您使用四参数表单develop时,git fetch remote refspec步骤只会 您要求的一个分支。有三个参数,即fetchgit fetch remote步骤通常会带来所有分支。只有两个参数,fetch通常会根据需要自动从git fetch获取,并再次带来所有分支。因此,您通常只需运行origin

2 如果您检查文件,您会看到以下内容:

git fetch

您可能还会看到更多行,例如:

a17c56c056d5fea0843b429132904c429a900229        branch 'master' of [url]

(或者你可能没有) - 这是ca00f80b58d679e59fc271650f68cd25cdb72b09 not-for-merge branch 'maint' of [url] 带来的所有东西。在这种特殊情况下,我运行了git fetch而没有任何参数,它带来了git pullmaster(以及更多项目)。所有提交ID都会在maint中结束,然后FETCH_HEAD脚本会提取 "用于合并"通过排除标记为" not-for-merge"。

的所有标记