2014-01-23 3 views
3

У меня есть нечеткое представление о том, что индекс git содержит как git-add s и git-commit s, но у меня нет подсказки о том, что происходит с этим содержимым, когда вы делаете git-merge. Мне особенно интересно узнать, что делает индекс, когда слияние происходит неудачно (например, из-за конфликта).Как содержимое индекса git развивается во время слияния (и что находится в индексе после неудачного слияния)?

+0

merge и rebase похожи в некоторых точках. Возможно, вы можете видеть, что происходит, выполняя 'git rebase -i' и заменяя все' pick' на 'edit', а затем наблюдая модификацию .git – Asenar

+0

@Asenar: сходство возникает, потому что' rebase' представляет собой серию 'cherry-pick' операции внутри и для каждой собранной вишни, git использует механизм слияния для применения изменений, подразумеваемых этим фиксатором. – torek

+0

благодарю вас за эту точность :) – Asenar

ответ

2

Для любого заданного пути в индексе есть до четырех «номеров версий», пронумерованных 0 (ноль) до 3. Я назову их «слотами», как если бы они были на самом деле для каждой записи, а затем легко индексируется (это облегчает их обсуждение), хотя на самом деле дополнительные версии вводятся динамически только тогда, когда это необходимо. Эти «виртуальные слоты» могут быть «пустыми», то есть файл не существует.

(На самом деле, как только запись создается в индексе, она помечается бит-бит, CE_REMOVED, если это необходимо. Это становится волосатым, потому что весь каталог, полный файлов, можно пометить «удаленным», а затем файл может быть созданный с именем предыдущего каталога и помеченным как «добавленный». Давайте просто притворимся, что у нас есть фиксированные слоты, там-но-пусто, вместо. :-))

Слот № 0 является «нормальным», не конфликтующим , все-хорошо. Он содержит кучу данных кэша, имя пути и идентификатор blob-ID (SHA-1) для файла, хранящегося в репозитории.

Когда слияние завершается успешно, все это «обычное дело», поэтому единственным частным случаем является конфликтное слияние. Слияние «конфликтует», когда слоты 1, 2 и/или 3 не являются пустыми. Пройдя большую часть механики, это происходит. Слияние использует «новейший» имя для всех слотов, а также:

  • слот ноль остается пустым (вы не можете «совершить», пока не разрешить конфликт, к тому времени этот слот не будет пустым если вы действительно не хотите, чтобы файл был удален).
  • Слот 1 («основание») заполнен общей версией предка. Если файл является новым (в обеих версиях), этот слот пуст.
  • Слот 2 («наш») заполнен мишенью (HEAD, если только вы не вручную ссылаетесь на некоторые из основных механизмов слияния). Если файл был удален в HEAD/target-of-merge, вместо этого этот слот пуст.
  • Слот 3 («их») заполнен версией, объединенной в бытие. Если файл был удален в ревизии, связанной с объединением, этот слот пуст.

После того, как вы разрешите конфликт и «добавьте git», слот # 0 будет заполнен всем, что вы «добавите», уничтожив записи с # 1 по # 3 или, если вы «git rm», конфликтный файл, остальные записи в стадии записи все еще удаляются, но теперь слот # 0 остается пустым, что также устраняет конфликт.

Более конкретно, то, что у вас есть общий предок, который имеет (среди прочих) эти два файла:

gronk 
flibby 

Вы находитесь на ветке cleanup и вы переименовали gronk в breem и редактировать как это и flibby. Вы принимаете решение git merge work, где они модифицировали gronk, но не переименовали его и удалили flibby. Некоторые другие файлы (файлы) сливаются чисто.

Индекс будет содержать три версии bleem и две версии flibby:

$ git checkout cleanup 
Switched to branch 'cleanup' 
$ git merge work 
CONFLICT (modify/delete): flibby deleted in work and modified 
in HEAD. Version HEAD of flibby left in tree. 
Auto-merging bleem 
CONFLICT (content): Merge conflict in bleem 
Automatic merge failed; fix conflicts and then commit the result. 
$ git ls-files --stage 
100644 4362aba7f3b7abf2da0d0ed558cbf5bc0d12e4b0 1 bleem 
100644 49db92a61392e9fd691c4af6e1221f408452a128 2 bleem 
100644 04b399c8fe321902ce97a1538248878756678ca2 3 bleem 
100644 366b52546711401122b791457793a38c033838dd 1 flibby 
100644 6fecb1480f45faaabc31b18c91262d03d3767cde 2 flibby 
100644 7129c6edb96d08bb44ca1025eb5ae41d41be8903 0 x.txt 

Вы можете увидеть оригинал (базовый) вариант bleemgit show :1:bleem с. Это было названо gronk в базовой версии (и в work, а в данном случае), но теперь это называется bleem, потому что git считает, что вы переименовали gronk в bleem в cleanup. (Git находит переименовывает между слиянием базы и HEAD, а затем применяет ту же переименовывать к work при необходимости, так как в этом случае.)

Кроме того, вы можете увидеть версию work с git show :3:bleem или git show work:gronk, а версия HEAD с любым из: git show HEAD:bleem, git show cleanup:bleem, или git show :2:bleem (слот 2 содержит HEAD aka cleanup, и назван в соответствии с наименованием в HEAD).

Для flibby, так как он был удален в work, нет версии «их» (слот 3).

Для устранения конфликтов вам необходимо сообщить только git add или git rm, чтобы обновить запись с нулевым номером и удалить записи с 1 по 3. Конечно, с git add, то, что идет в слот 0, теперь находится в рабочем каталоге, поэтому вам обычно приходится сначала редактировать файлы.

Кстати, я обозначил слоты 2 и 3 «наши» и «их» выше. Так как git checkout обрабатывает их (git checkout --ours и git checkout --theirs, вы можете написать версию 2 или 3 в слот 0, такая проверка, как и большинство проверок, также «стирает» другие слоты, тем самым разрешая конфликт). Тем не менее, в rebase ветвь HEAD на самом деле является ветвью, переустановленной на, а «их» версия - это ваше подразделение-перераспределение. Таким образом, наша/терминология на самом деле не такая уж большая, на мой взгляд: слишком легко вернуть ее во время перебазы.

Следует также отметить, что git checkout -m будет «воссоздавать» конфликт слияния, если вы находитесь в середине конфликтного слияния, стирая слот 0 и «воскрешая» версии в слотах 1-3 по мере необходимости (и записывать конфликтуемый файл слияния в рабочий каталог, выполняя любые изменения в настройке merge.conflictstyle).

+0

Это очень хороший ответ. –

Смежные вопросы