为什么我要合并“远程跟踪分支'origin/develop'到develop”?

156

我是我们组织中唯一用以下信息做提交的人:

合并远程跟踪分支'origin/develop'到develop

不确定我是如何引起这些提交的,但我想停止它们。

我使用了哪个命令来创建此提交,并且我应该使用哪个正确的命令以避免产生此提交?


1
Richard Hansen的回答很好。但我认为对于初学者来说可能会有些困惑。我的解决方案是继续使用pull --rebase,但在进行pull之前先将更改存储起来。然后,在拉取后,我再应用它。我解决冲突。最后,我可以提交并推送。 - Johnjohn
git pull --autostash --rebase 对你来说可行吗,@Johnjohn? - sourcedelica
3个回答

242

git pull 可能会创建提交。如果您在本地进行了提交,然后在其他人将提交推送到存储库后运行git pull,Git会下载其他开发人员的提交,然后将其合并到您的本地分支中。

如何避免这些合并提交

您可以使用 git pull --rebase 来防止这种情况发生,但是变基有其风险,我建议完全避免使用pull命令

相反,我鼓励您遵循以下使用模式:

# download the latest commits
git remote update -p

# update the local branch
git merge --ff-only @{u}

# if the above fails with a complaint that the local branch has
# diverged:
git rebase -p @{u}

解释

  • git remote update -p downloads all of the commits in the remote repositories and updates the remote tracking branches (e.g., origin/master). It does NOT touch your working directory, index, or local branches.

    The -p argument prunes deleted upstream branches. Thus, if the foo branch is deleted in the origin repository, git remote update -p will automatically delete your origin/foo ref.

  • git merge --ff-only @{u} tells Git to merge the upstream branch (the @{u} argument) into your local branch but only if your local branch can be "fast forwarded" to the upstream branch (in other words, if it hasn't diverged).

  • git rebase -p @{u} effectively moves the commits you've made but haven't yet pushed on top of the upstream branch, which eliminates the need to create the silly merge commits you're trying to avoid. This improves the linearity of the development history, making it easier to review.

    The -p option tells Git to preserve merges. This prevents Git from linearizing the commits being rebased. This is important if, for example, you merged a feature branch into master. Without -p, every commit on the feature branch would be duplicated on master as part of the linearization done by git rebase. This would make the development history harder to review, not easier.

    Beware: git rebase might not do what you expect it to do, so review the results before pushing. For example:

    git log --graph --oneline --decorate --date-order --color --boundary @{u}..
    

我更喜欢这种方法,而不是使用git pull --rebase,原因如下:

  • 它允许您在修改历史以包含它们之前查看传入的上游提交
  • 它允许您将-p (--preserve-merges)选项传递给git rebase,以防需要对有意合并(例如,已推送的特性分支合并到master)进行变基。

简写:git up代替git pull

为了使上述操作变得容易,建议创建一个名为up的别名:

git config --global alias.up '!git remote update -p; git merge --ff-only @{u}'

现在,要将您的分支更新到最新状态,只需运行以下命令:
git up

不要使用git pull,如果你遇到错误,因为本地分支与上游分支发生了分歧,那就是提示你需要变基的时候了。

为什么不用git pull --rebase

运行git pull --rebase等同于运行git fetch然后运行git rebase。它尝试快进到新的上游提交,但如果这不可能,它将把你的本地提交变基到新的上游提交上。这通常没问题,但要小心:

  • 变基是一个高级主题,你应该在变基之前理解其影响。
  • git pull --rebase不允许你在合并提交之前检查提交。根据上游的更改情况,重新设置可能是错误的操作——rebase --ontomergeresetpush -f可能比普通的rebase更合适。
  • 目前不可能向变基操作传递--preserve-merges,因此任何特性分支的有意合并都将被线性化,重放(因此复制)所有特性分支提交。

通过git pull创建的现有合并提交的“修复”

如果您还没有推送通过git pull创建的合并提交,您可以通过变基来消除合并提交。假设您没有进行任何有意的合并(例如将已经推送的特性分支合并到当前分支中),则以下命令应该可以解决问题:
git rebase @{u}

上述命令告诉Git选择从HEAD(当前提交)可达的所有非合并提交,减去从@{u}(即“上游分支”,如果HEAD是master,则为origin/master)可达的所有提交,将它们重放(cherry-pick)到上游分支的顶部,然后移动当前分支引用以指向重放提交的结果。这有效地将非合并提交移动到最近的上游提交,从而消除了由git pull创建的合并。
如果您有一个有意的合并提交,您不想运行git rebase @{u},因为它会重放来自另一个分支的所有内容。处理这种情况要复杂得多,这就是为什么最好使用git up并完全避免git pull的原因。您可能需要使用reset取消pull创建的合并,然后执行git rebase -p @{u}。对于我来说,git rebase的-p参数不可靠,因此您可能需要使用reset撤消有意的合并,将本地分支更新到@{u},然后重新进行有意的合并(如果有许多棘手的合并冲突,则很麻烦)。

1
+1 是因为你讨论了 --preserve-merges,但是你并没有在你告诉他运行的命令中记录下来,所以-1。 - Seth Robertson
3
git remote update -pgit fetch 有什么区别? - eckes
3
@eckes:git remote update -pgit fetch --all -p相同。我养成了使用git remote update -p的习惯,当时fetch没有-p选项。 - Richard Hansen
1
@user1914692:合并完成后,Git会将本地分支更新到指向新创建的合并提交,而不是远程分支的同一提交。这个新的合并提交是问题所在,特别是在推送时。 - Richard Hansen
2
git-rebase 文档中说明 -p/--preserve-merges 已弃用,现在应使用 -r/--rebase-merges - Scott Martin
显示剩余14条评论

22
git fetch
git rebase origin/master

应该就这样了。或者如果你想继续使用pull

git pull --rebase

您还可以在配置中设置该分支自动变基,或者为您创建的任何其他跟踪分支自动设置。然后,您就可以回到只使用

git pull

关于这个问题的更多信息,请参见此页面中的“使用变基拉取而不是合并”部分:

https://mislav.net/2010/07/git-tips/


0
合并远程跟踪分支'origin/develop'到develop 这是一个git pull,将origin/develop(远程更改)合并到develop(本地更改),我们因此遇到了很多问题,代码丢失等。
所以现在我们的工作流程可以防止任何与git pull合并相关的问题,并保持简单。基本上就像一个rebase,但通过合并分支轻松实现在最基本的GUI中。其他更改总是合并到你的更改中,因此在冲突的情况下,你只需要修复影响你更改的行即可!只有你的更改出现在最终提交中。
  1. 检出并拉取develop
  2. 从develop创建一个功能分支X
  3. 在X上完成你的工作
  4. 为了获取可能的传入更改,请检出并拉取develop
  5. 如果有远程更改,则将develop合并到X
  6. 如果有冲突,请解决它们
  7. 如果你执行了5或6,则返回到4
  8. 将X合并到develop
  9. 推送develop

是的,看起来有点麻烦,改变分支、拉取等等。但是如果你查看 rebase 文档,他们警告说不要在共享分支中使用它。所以你最终还是需要创建相同的 X 分支,然后 git fetch origin develop 和 git rebase origin/develop,你仍然需要将重新基于的 X 分支合并回共享分支 develop,所以工作量相同。

通常情况下,如果在步骤 5 发生了远程更改,尤其是在步骤 6 发生了冲突。你需要再次测试,这需要时间,所以你会回到步骤 4。在步骤 8 和 9 中存在竞态条件,但这只是一个极端情况,可能会有其他人在你之前推送变更。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接