git - 尽可能早地重新排序分支上的提交而不会发生冲突

时间:2011-12-20 18:20:58

标签: git conflict rebase

如何在没有任何冲突的情况下尽快提交分支提交(没有太多的手工工作,例如rebase -i)?

例如

A-B-C-d-X

应该成为

A-B-X-C-d

如果用C和D交换X没有冲突但是用B交换X会导致冲突。

感谢。

3 个答案:

答案 0 :(得分:2)

使用git rebase -i X~,其中X~X之前的修订版。

然后将rebase日志中的行重新排序为您所需的顺序。

More about interactive rebase

答案 1 :(得分:2)

以下是15分钟黑客攻击后我想出的内容。它不是解决问题的完整解决方案,但它应该减少所涉及的工作。

目标是使用git bisect为将来的提交找到最早的无冲突合并点。该解决方案利用git bisect中固有的二进制搜索功能来减少步骤。

不幸的是,这个不会阻止以后提交冲突,因此需要一个交互式的rebase来审核结果(但无论如何这都是重点)。

一个缺点/警告是,当您在测试补丁时指示步骤是否失败或成功时,您必须扭转头部goodbad的感觉。

如果以下任何步骤不清楚,请告诉我,我会详细说明。

首先在一系列提交中创建以下文件。每个提交应该添加一系列四个相同的行(a,然后是b,然后是c,然后是d's)。

a
a
a
a
b
b
b
b
c
c
c
c
d
d
d
d

此时,git log应输出如下内容:

commit 6f2b809863632a86cc0523df3a4bcca22cf5ab17
Author: Todd Sundsted <...>
Date:   Tue Dec 20 22:45:44 2011 -0500

    Added d.

commit 91ba7e6f19db74adb6ce79e7b85ea965788f6b88
Author: Todd Sundsted <...>
Date:   Tue Dec 20 22:44:26 2011 -0500

    Added c.

commit f83beee55d6e060536584852ebb55c5ac3b850b2
Author: Todd Sundsted <...>
Date:   Tue Dec 20 22:44:00 2011 -0500

    Added b.

commit d6d924b0a30a9720f6e01dcc79dc49097832a587
Author: Todd Sundsted <...>
Date:   Tue Dec 20 22:43:38 2011 -0500

    Added a.

commit 74d41121470108642b1a5df087bc837fdf77d31c
Author: Todd Sundsted <...>
Date:   Tue Dec 20 22:43:11 2011 -0500

    Initial commit.

现在编辑文件,使其包含以下内容,然后提交:

a
a
a
a
b
x
x
b
c
x
x
c
d
d
d
d

日志现在应该再包含一次提交:

commit 09f247902a9939cb228b580d39ed2622c3211ca6
Author: Todd Sundsted <...>
Date:   Tue Dec 20 22:46:36 2011 -0500

    Replaced a few lines with x.

现在为X提交生成补丁。

git diff -p master~ > x.patch

曲解bisect - 记得在补丁失败时使用git bisect good,补丁成功时使用git bisect bad

$ git bisect start
$ git bisect good 74d41121470108642b1a5df087bc837fdf77d31c
$ git bisect bad master
Bisecting: 2 revisions left to test after this (roughly 1 step)
[f83beee55d6e060536584852ebb55c5ac3b850b2] Added b.
$ patch --dry-run -p1 < x.patch 
patching file file.txt
Hunk #1 FAILED at 3.
1 out of 1 hunk FAILED -- saving rejects to file file.txt.rej
$ git bisect good
Bisecting: 0 revisions left to test after this (roughly 1 step)
[6f2b809863632a86cc0523df3a4bcca22cf5ab17] Added d.
$ patch --dry-run -p1 < x.patch 
patching file file.txt
$ git bisect bad
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[91ba7e6f19db74adb6ce79e7b85ea965788f6b88] Added c.
$ patch --dry-run -p1 < x.patch 
patching file file.txt
Hunk #1 succeeded at 3 with fuzz 2.
$ git bisect bad
91ba7e6f19db74adb6ce79e7b85ea965788f6b88 is the first bad commit
commit 91ba7e6f19db74adb6ce79e7b85ea965788f6b88
Author: Todd Sundsted <...>
Date:   Tue Dec 20 22:44:26 2011 -0500

    Added c.

$ git bisect reset

正如预期的那样,commit X中的编辑可以在提交C后立即移动。交互式rebase确认了这一点:

91e92489 * Added d.
6c082b1f * Replaced a few lines with x.
a60ae2a9 * Added c.
4d5e78f2 * Added b.
7d2ff759 * Added a.
74d41121 * Initial commit.

答案 2 :(得分:0)

嗯,这几乎可行但需要一些清理。

使用它一段时间之后,我遇到了另一个问题,我发布了here

#!/bin/sh -e

# todo: integrate with git
GIT_DIR=./.git/

commitid=$1

if [ "$1" = "" ]; then
   echo usage: $0 commitid
   exit 1
fi

tmpdir="$GIT_DIR/bubble-work"
/bin/rm -rf "$tmpdir"
mkdir "$tmpdir"

# checkout commit with detached head
git checkout -q $commitid^0 || die "could not detach HEAD"

while [ 1 = 1 ]; do

# todo pipe output to avoid temp files
# see git-rebase.sh

patchfile=`git format-patch -k --full-index --src-prefix=a/ --dst-prefix=b/ --no-renames -o "$tmpdir" HEAD~1`
echo patch = $patchfile

git checkout -q HEAD~2
git am --rebasing "$patchfile" || die "git am failed"
/bin/rm -f "$patchfile"

echo looping
done



/bin/rm -rf "$tmpdir"