Как повторить разрешение конфликта слияния после работы с несвязанными коммитами, которые были перед ним с rebase -ir? - PullRequest
1 голос
/ 09 марта 2019

Для простого примера, скажем, у нас есть репо, в котором в файл была добавлена ​​неправильная строка a.

$ git init 
Initialized empty Git repository in /someplace/.git/
$ echo "a1\nb2" > a
$ echo b1 > b    
$ git add .
$ git commit -m init  
[master (root-commit) 917f3b9] init
 2 files changed, 3 insertions(+)
 create mode 100644 a
 create mode 100644 b

Ветвь master, затем разветвляется на новую ветвь f.

$ git branch f

В master мы добавляем еще одну строку в неверный файл.

$ echo b3 >> a
$ git commit -am 'added b3 to a' 
[master e44bc9f] added b3 to a
 1 file changed, 1 insertion(+)

В ветке f мы делаем что-то не связанное, фиксируем это,

$ git checkout f
$ echo c1 > c 
$ git add .
$ git commit -m "added c"
  1 label onto
[f 7cb63b2] added c
 1 file changed, 1 insertion(+)
 create mode 100644 c

затем мы перемещаем строку, неправильно помещенную в файл a, в файл b.

$ echo b2 >> b
$ sed -i '/b2/d' a
$ git commit -am "moved b2 to where it really belongs"
[f 32cee76] moved b2 to where it really belongs
 2 files changed, 1 insertion(+), 1 deletion(-)

Затем мы пытаемся объединить master с f, но столкнулись с конфликтом, который master добавил еще одну неправильную строку, в то время как f удалил первую.

$ git merge master 
Auto-merging a
CONFLICT (content): Merge conflict in a
Automatic merge failed; fix conflicts and then commit the result.
$ cat a
a1
<<<<<<< HEAD
=======
b2
b3
>>>>>>> master

Чтобы разрешить конфликт, мы перемещаем вторую неправильную строку в правильный файл и фиксируем слияние.

$ echo b3 >> b
$ sed -i '/HEAD/,$d' a
$ git commit -a --no-edit 
[f 28d8543] Merge branch 'master' into f

Затем мы понимаем, что коммит около c не должен находиться в этой ветке, поэтому мы «удаляем» его с помощью rebase -ir и встречаемся с тем же конфликтом, что и ранее.

$ git rebase -ir $(git merge-base master @) # remove the commit about c
Auto-merging a
CONFLICT (content): Merge conflict in a
Could not apply 28d8543... onto # Merge branch 'master' into f
$ cat a
a1
<<<<<<< HEAD
=======
b2
b3
>>>>>>> refs/rewritten/onto

Итак, какое самое простое, наиболее эффективное и универсальное решение здесь, чтобы восстановить предыдущее разрешение, принимая во внимание то, что было добавлено в b, которое не появляется в конфликте?

Ответы [ 3 ]

1 голос
/ 09 марта 2019

Существует утилита git для записи разрешения конфликта, чтобы вы могли воспроизвести его позже.Это называется git rerere.

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

Я бы также сказал, что с хорошимрабочий процесс, сценарий, который вы описываете, должен быть нечастым, если не вообще существующим, поэтому я лично не стал бы использовать rerere для записи каждого разрешения конфликта только на случай, если он понадобится мне позже.

Но... поскольку вы задали этот вопрос, git rerere, вероятно, является "ответом".

0 голосов
/ 15 июля 2019

git rerere или создание патча refs/rewritten/onto необходимо, потому что с Git 2.23 refs/rewritten/onto будет удалено в конкретном случае, когда git rebase -ir отменяется.
"git rebase --abort" используется дляоставьте refs/rewritten/ при выводе "git rebase -r", что было исправлено.

См. commit d559f50 , commit 37e9ee5 , commit d3fce47 , commit 7372eae (14 мая 2019) Phillip Wood (phillipwood) .
(объединено Junio ​​C Hamano- gitster - в коммит 88f95e4 , 09 июля 2019 г.)

rebase --abort/--quit: очистка refs/rewritten

Когда rebase -r завершает работу, он удаляет все ссылки в соответствии с refs/rewritten, которые он создал.
Однако, если пользователь прерывает работу или выходит, ссылки на исправления не удаляются.Это может вызвать проблемы для будущих перебазировок.

Например, недавно я хотел объединить обновленную версию ветки темы с веткой интеграции, поэтому запустил rebase -ir и удалил медиаторы и метку для ветки темы из списка задач, чтобы

merge -C <old-merge> topic

выберет новую версию темы.
К сожалению, * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

* * * * * * * * * * * * * * * * * * * * 10 * * * 10 10 *.Логика для неинтерактивного случая выхода изменена, чтобы гарантировать, что
buf всегда освобождается.
0 голосов
/ 09 марта 2019

Лучшее решение, которое до сих пор приходит на ум (что на самом деле не так уж и хорошо) - это отказаться от git и сделать патч для разрешения конфликта слияния:

$ cp -a . ../$(basename $PWD)~
$ echo b3 >> b
$ sed -i '/HEAD/,$d' a
$ diff -ru ../$(basename $PWD)~ .
diff -ru ../t~/a ./a
--- ../t~/a 2019-03-08 12:54:34.701197573 -0800
+++ ./a 2019-03-08 12:54:56.761197321 -0800
@@ -1,6 +1 @@
 a1
-<<<<<<< HEAD
-=======
-b2
-b3
->>>>>>> refs/rewritten/onto
diff -ru ../t~/b ./b
--- ../t~/b 2019-03-08 12:54:34.701197573 -0800
+++ ./b 2019-03-08 12:54:54.044530686 -0800
@@ -1,2 +1,3 @@
 b1
 b2
+b3

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

Я бы предпочел решение, использующее git для управления этим.

...