拉取后的 Git Rebase 操作

16

如果我直接在主分支上工作(虽然我尽量避免这样做),我通常使用git pull --rebase。但是如果我忘记了进行变基并执行了git pull,有没有一种方法可以撤销此操作并使它线性化,而不是合并提交?此时进行变基是否明智(如果可以的话)?

我知道我可以默认启用拉取时的变基操作,以便不会忘记,但这更多地涉及到在这种情况下应该做什么。


3
我猜 git reset --hard 回到 pull 之前的状态,然后重新进行 pull 是正确的方法。 - Alexander Oh
谢谢。您能将此作为答案而不是评论发布吗? - Jeff Storey
3个回答

16

简短回答(已由@Alex在评论中给出):git reset --hard HEAD^,但仅当存在合并提交时才有效(否则你只是从快进备份了一个提交)。

带说明的长版本:

git pull实际上就是git fetch后跟git merge(除非你使用--rebase进行覆盖,就像你所提到的那样)。因此,你只需要查看是否得到了一个实际的合并提交:

$ git pull
Updating 171ce6f..523bacb
Fast-forward
 mp.py |   24 ++++++++++++++++++++++++
 1 files changed, 24 insertions(+), 0 deletions(-)
 create mode 100644 mp.py

在这种情况下没有合并提交,只是快速前进,所以不用担心 - 没有要rebase的更改!如果您执行git log,尤其是在下面执行图形化操作时,将会看到缺少合并提交。
让我们强制执行一次合并。
$ git reset --hard HEAD^
HEAD is now at 171ce6f ignore *.log files

[现在我落后于remotes/origin/master一步]

$ echo '# pointless comment' >> selfref.py
$ git add selfref.py 
$ git commit -m 'added to force merge'
[master 260e129] added to force merge
 1 files changed, 1 insertions(+), 0 deletions(-)
$ git pull
Merge made by recursive.
 mp.py |   24 ++++++++++++++++++++++++
 1 files changed, 24 insertions(+), 0 deletions(-)
 create mode 100644 mp.py

我们可以看到即使上面的文本缺失,这一事件仍然发生,具体表现为:
$ git log --graph --decorate --abbrev-commit --pretty=oneline
*   c261bad (HEAD, master) Merge branch 'master' of [ssh url]
|\  
| * 523bacb (origin/master, origin/HEAD) add multiprocessing example
* | 260e129 added to force merge
|/  
* 171ce6f ignore *.log files

我们希望将本地分支名 master 再次指向(在这种情况下)260e129。幸运的是,这个命名非常容易实现。
$ git rev-parse HEAD^
260e1297900b903404c32f3706b0e3139c043ce0

(当前这个两个父提交合并的另一个父提交是 HEAD^2.) 所以:

$ git reset --hard HEAD^
HEAD is now at 260e129 added to force merge

现在我们可以将分支变基到 remotes/origin/master(我会使用非常简短的名称 origin 来命名它):

$ git rebase origin
First, rewinding head to replay your work on top of it...
Applying: added to force merge

现在,图形化的一行日志显示为:

$ git log --graph --decorate --abbrev-commit --pretty=oneline
* 4a0b2e2 (HEAD, master) added to force merge
* 523bacb (origin/master, origin/HEAD) add multiprocessing example
* 171ce6f ignore *.log files

从所有这些中,您应该能够确定如果运行git pull并且它抱怨合并失败,该怎么办。:-)

4
我猜想使用 git reset --hard 回到拉取之前的状态,然后重新拉取是解决问题的方法。

3

我想给你一些建议,帮助保持历史线性。为了在拉取时自动将分支进行变基,请设置以下git配置。

$ git config branch.autosetuprebase always

应用此设置后,您无需使用--rebase参数输入完整的拉取命令,只需使用git pull即可。

您可以在这篇文章中获得更多信息: http://stevenharman.net/git-pull-with-automatic-rebase


1
正如我在问题中所述,我知道我可以做到这一点。我只是想学习在这种情况下该怎么做。 - Jeff Storey
1
在 git 版本 >= 1.7.9 中,这是git config --global pull.rebase true - lleo

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