Git Rebase -> 为什么pull的时候有merge?

Git Rebase -> Why is there a merge when pulling?

我创建了一个分支来开发新功能。由于此新功能完全是作为一个新项目开发的,因此唯一可能的冲突源将在解决方案文件中。

随着功能的开发,主分支更新了几次。当我完成开发和测试时,我做了:

git checkout master
git fetch
git pull
git checkout myFeature
git rebase master

rebase(和所有其他命令)运行良好,没有 conflicts/errors/problems 报告。我的下一步是 git status,结果是:

On branch myFeature
Your branch and 'origin/myFeature' have diverged, and have 7 and 5 different commits each, respectively. (use "git pull" to merge the remote branch into yours)

当我 git pull 打开合并并查看历史记录时,我的提交被重复了。在我看来,这种重复是不应该发生的。我期待我的提交应该在最后一次(当前)提交之后重新应用。

是我做错了什么还是我的期望有误?

为什么会有合并提交

当你做一个变基时,你正在改变 Git 历史。当您再次拉取时,Git 会再次尝试合并这两个历史记录。默认情况下 git pullgit fetch + git merge,这将导致合并提交。

更改历史记录后这不是您想要的,因为它会(部分)恢复您对历史记录的更改。不幸的是 git status 的提示有点误导......

变基/更改历史后你应该做什么

更改历史记录(例如变基)后,您需要强制推送,这样您也可以在远程上获得该历史记录。你告诉 git 然后 "the history is different, but trust me, that's intended".

建议使用 "force push with lease":git push --force-with-lease - 参见 git push --force-with-lease vs. --force

修复当前状态的步骤

幸运的是,您可以使用 Git reflog 在 git pull 之前返回!

这将修复错误的拉取,不会有任何冲突需要解决:)

所以要执行的步骤:

  1. 在 reflog git reflog 中找到正确的提交,所以在 git pull 之前(注意:您可以通过键入 q 退出 reflog)
  2. Git 重置为该提交,例如git reset 327fb961e --hard
  3. 仔细检查并执行 git push --force-with-lease

注意:如果 git reset 有误,您可以再次使用 git reflog :)

注意 2:reflog 仅在您的本地计算机上

这部分足以用于 master 分支的变基。

git checkout master
git fetch
git pull
git checkout myFeature
git rebase master

但是,您可以只使用下面的命令来代替上面的所有命令来做同样的事情。

$ git pull origin master --rebase

在此之后,所有提交哈希将被重写,这就是为什么 git status 显示您的分支已经分歧。

忽略这一点,您可以运行以下命令将重新设置基础的代码推送到远程分支。

$ git push origin HEAD -f

在变基过程中,如果遇到冲突,不想继续变基,可以运行 git rebase --abort中止变基。

无论如何,如果您发现自己正处于一些不希望的提交相关危险之中,您可以按照以下步骤操作。

  • git reflog - 找到最后的完美提交并记下它的提交哈希值
  • git reset --hard <commit-hash> - 提供最后的完美提交散列

它将带您到 repo 的最后一个完美代码。

之前的答案看起来不错。只是想直观地说明发生了什么,以防有帮助:

由于 git rebase 修改了历史记录,你在 rebase 后的分支看起来与你在 origin 上的分支不同。

origin/master:

A -> B -> C -> D -> E

你的分行,origin/yourbranch:

A -> B -> F -> G -> H

变基后,yourbranch 看起来像:

A -> B -> C -> D -> E -> F -> G -> H

然后,当你拉动origin/yourbranch时,你会得到:

A -> B -> C -> D -> E -> F -> G -> H - I (merge commit)
      \                              /
        -> F -> G -> H -------------

由于历史不同,所以变成正常的非快进合并。实际上,您的远程和本地分支已成为不同的分支。