且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

解决合并冲突后,Git rebase卡住了

更新时间:2022-10-29 14:32:24

一个可能的原因是 git rebase 被困在rebase循环中的是 git gc

这在 git 2.7.1(2016年2月6日)



请参阅 commit 8c24f5b (2016年1月13日) peff )

(由 Junio C Hamano - gitster - commit eefc461 ,2016年1月26日)
$ b


rebase :忽略来自 gc --auto



重新绑定后,我们称之为 gc --auto 来清洁您如果我们创造了很多松散的物体。但是,我们在&& - 链中这样做。如果 gc --auto 失败(例如,因为之前的背景gc通过保留 gc.log ),那么:


  1. 我们将无法清理状态目录,导致用户永远停留在rebase(甚至 git am --abort 不起作用,因为它会调用 gc --auto !)。

  2. 在某些情况下,我们可能会从rebase返回一个伪造的退出代码,指示除auto-gc之外的所有内容都成功失败。

我们可以通过忽略 gc --auto 的退出码来解决这个问题。

因此,要解决您只需删除 gc.log

  rm .git / gc.log 


I'm running a rebase that hits a conflict:

$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: Better `SelectMotifsView.js`
Using index info to reconstruct a base tree...
M       browser/AddLinkView.js
M       browser/SelectMotifsView.js
M       browser/index.html
Falling back to patching base and 3-way merge...
Auto-merging browser/index.html
CONFLICT (content): Merge conflict in browser/index.html
Failed to merge in the changes.
Patch failed at 0001 Better `SelectMotifsView.js`
The copy of the patch that failed is found in:
   /Users/dmitry/dev/links/.git/rebase-apply/patch

When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".

No biggie—I had made a small change that I knew would cause a conflict:

diff --cc browser/index.html
index ba9c4f3,4c2a1c2..0000000
--- a/browser/index.html
+++ b/browser/index.html
@@@ -40,6 -40,7 +40,10 @@@
              <label>
                  <%= label %>
                  <select class="form-control" name="motif">
++<<<<<<< HEAD
++=======
+                     <% console.log(exclude); %>
++>>>>>>> Better `SelectMotifsView.js`
                      <% motifs.each(function(motif) { if (!exclude || exclude.indexOf(motif) < 0) { %>
                          <option value="<%= motif.get('id') %>"><%= motif.get('name') %></option>
                      <% } }); %>

I want to keep the version from HEAD, which is empty, so I go in and just remove the whole:

++<<<<<<< HEAD
++=======
+                     <% console.log(exclude); %>
++>>>>>>> Better `SelectMotifsView.js` 

I save the file, browser/index.html, then git add browser/index.html:

$ git add browser/index.html
$ git rebase --continue

But then:

Applying: Better `SelectMotifsView.js`
No changes - did you forget to use 'git add'?
If there is nothing left to stage, chances are that something else
already introduced the same changes; you might want to skip this patch.

When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".

Never seen this before... git status shows no remaining unresolved paths. What to do? I read on other related questions that this may be a good use of --skip, but this doesn't seem to be a null commit. Or am I wrong?

One possible cause of a git rebase being stuck in a "rebase loop" is git gc.
This is fixed in git 2.7.1 (February 6th, 2016)

See commit 8c24f5b (13 Jan 2016) by Jeff King (peff).
(Merged by Junio C Hamano -- gitster -- in commit eefc461, 26 Jan 2016)

rebase: ignore failures from "gc --auto"

After rebasing, we call "gc --auto" to clean up if we created a lot of loose objects. However, we do so inside an &&-chain. If "gc --auto" fails (e.g., because a previous background gc blocked us by leaving "gc.log" in place), then:

  1. We will fail to clean up the state directory, leaving the user stuck in the rebase forever (even "git am --abort" doesn't work, because it calls "gc --auto"!).
  2. In some cases, we may return a bogus exit code from rebase, indicating failure when everything except the auto-gc succeeded.

We can fix this by ignoring the exit code of "gc --auto".

So to fix you just need to remove gc.log:

rm .git/gc.log