git - переупорядочить коммит на ветке как можно раньше без конфликта - PullRequest
4 голосов
/ 20 декабря 2011

Как мне продвинуть коммит вверх по ветке, чтобы он был как можно раньше без каких-либо конфликтов (без особой ручной работы, например, rebase -i)?

Например

А-В-С-D-Х

должно стать

А-В-Х-С-D

, если замена X на C и D не имеет конфликтов, но замена X на B приведет к конфликту.

Спасибо.

Ответы [ 3 ]

2 голосов
/ 21 декабря 2011

Вот демонстрация того, что я придумал после 15 минут взлома. Это не полное решение поставленной проблемы, но оно должно сократить объем работы.

Цель состоит в том, чтобы использовать git bisect, чтобы найти самую раннюю бесконфликтную точку слияния для будущего коммита. В этом решении используются возможности двоичного поиска, присущие git bisect, для сокращения шагов.

К сожалению, это не не исключает конфликты последующих коммитов, поэтому для проверки результатов требуется интерактивная перебазировка (но в любом случае это главное).

Единственный недостаток / предостережение заключается в том, что вы должны обратить вспять смысл good и bad в своей голове, когда вы инструктируете git о том, был ли этот шаг неудачным или успешным при тестировании патча.

Если какой-либо из приведенных ниже шагов неясен, дайте мне знать, и я постараюсь уточнить.

Сначала создайте следующий файл в серии коммитов. Каждый коммит должен добавлять серию из четырех одинаковых строк (a, затем b, затем c, затем d).

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 commit.

git diff -p master~ > x.patch

Crank up 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

Как и ожидалось, изменения в коммите X могут быть перемещены сразу после коммита C. Интерактивная перебазировка подтверждает это:

91e92489 * Added d.
6c082b1f * Replaced a few lines with x.
a60ae2a9 * Added c.
4d5e78f2 * Added b.
7d2ff759 * Added a.
74d41121 * Initial commit.
2 голосов
/ 20 декабря 2011

Используйте git rebase -i X~, где X~ - это версия до X.

. Затем измените порядок строк в журнале перебазировки в соответствии с желаемым порядком.

Подробнееоб интерактивной перебазировке .

0 голосов
/ 21 декабря 2011

Ну, это в значительной степени работает, но нуждается в некоторой очистке.

Поработав некоторое время, я столкнулся с другой проблемой, которую выложил здесь .

#!/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"

...