Как изменить последовательные коммиты так, чтобы они ссылались на коммиты других подмодулей? - PullRequest
0 голосов
/ 04 июля 2019

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

Итак, я сделал интерактивный ребаз в родительском репозитории. Я хотел изменить два коммита в родительском репозитории, которые относятся к двум другим коммитам в подмодуле, например:

---A---B---C---D--- parent
   |   |
   v   v
---a---b--- sub

Поэтому я делаю git rebase -i A^ и выбираю для редактирования A и B:

edit A ...
edit B ...
pick C ...
pick D ...

Теперь я нахожусь в коммите А. Чтобы восстановить правильный идентификатор коммита подмодуля, я сначала проверяю соответствующий коммит субмодуля, а затем исправляю коммит в родительском репозитории.

$ cd sub/
$ git checkout a
$ cd ..
$ git add sub
$ git commit --amend

Кажется, хорошо, поэтому я перехожу к следующему:

$ git rebase --continue

Теперь он жалуется, что не может слиться. Вот мой перевод из локализованного сообщения:

Error merging submodule sub (Commits do not follow any merge base)
automatic merge of sub
CONFLICT (submodule): Merge conflict in sub
error: Could not apply B (B's commit message)
Resolve all conflicts manually, mark them as resolved with
"git add/rm ", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply B (B's commit message)

Достаточно справедливо. Второй коммит потерял связь с первым из-за измененного идентификатора субмодуля в первом. git status говорит changed by both: sub. Неуклонно, я пытаюсь изменить еще раз:

$ cd sub/
$ git checkout b
$ cd ..
$ git add sub
$ git commit --amend

К сожалению, это не делает то, что я хочу. Причина в том, что ошибочный git rebase --continue каким-то образом полностью проглотил коммит B. Изменения Б были внесены в область подготовки, но коммит пропал. Поэтому второй git commit --amend изменит A и поместит все изменения из B в A! Теперь, я думаю, я мог бы создать новый коммит в этот момент, реплицируя B. Но получить его точно так же, как B, было бы довольно сложно.

Как правильно изменить ссылки на подмодули? Почему и при каких обстоятельствах перебазировка уничтожает такие коммиты?

1 Ответ

1 голос
/ 05 июля 2019

TL; DR: У git commit без --amend используется git rebase --continue, что сделает git commit без --amend.

Дольше

Давайте возьмем исходную диаграмму за вычетом соединений с подмодулем (поскольку они ненадежны и мешают :-)):

...--o--A--B--C--D   <-- branch

Вы запускаете git rebase -i A^и измените A на edit (и так далее).Перенесите cherry-picks A в новую копию A':

...--o--A--B--C--D   <-- branch
      \
       A'  <-- HEAD

Вы делаете свое обновление, git add и git commit --amend, чтобы создать новое A", оставляя A' позади какотменено:

       A"   <-- HEAD
      /
...--o--A--B--C--D   <-- branch
      \
       A'

Теперь, независимо от того, что вы вводите для инструкций для B, Git пытается скопировать B , но не может .Таким образом, перебазирование останавливается на:

       A"   <-- HEAD
      /
...--o--A--B--C--D   <-- branch
      \
       A'

с некоторыми незафиксированными изменениями в индексе и рабочем дереве. Пока нет коммита B'. Есть две вещи, которые вы можете сделать сейчас.Один - сделать это самостоятельно:

<fix the submodule>
git add sub
git commit

Это создает B':

       A"-B'   <-- HEAD
      /
...--o--A--B--C--D   <-- branch
      \
       A'

, и теперь вы можете git rebase --continue, чтобы Git перешел к следующей части инструкции.(следовательно, вам не нужно просить отредактировать B изначально, вы можете просто продолжить копирование C в C' сейчас: если Git сейчас останавливается, чтобы позволить вам редактировать B', вы можете просто сказать, чтобы продолжить).

Другой - поскольку git commit теперь требует, чтобы вы напечатали сообщение коммита, - это настроить все, и вместо git commit запустите git rebase --continue, чтобы Git make B':

<fix the submodule>
git add sub
git rebase --continue

Шаг --continue замечает, что все конфликты исправлены (или жалуется и останавливается, если их нет), а затем выполняет git commit и продолжается, точно так же, как если бы вы сделалисделайте это сами.

Сводка

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

Сложно знать заранее - в некоторых случаях это может быть и невозможно - узнать, какие вишневые кирки будут успешными, а какие - неудачными.Таким образом, вам приходится уделять много внимания точным сообщениям, которые появляются непосредственно перед тем, как git rebase останавливается, чтобы позволить вам что-то сделать: он остановился, потому что вишневый пик не смог , или он остановилсяпотому что вы сказали, чтобы он остановился после успешного выбора вишни ? Другими словами, есть ли коммит, который вы должны --amend сейчас, или вы (должны Git) сделать new * 1089?* коммитить сейчас?

(Я сам запутался в этом. Я нахожу это довольно раздражающим.)

...