Я не могу сказать это достаточно раз: история, о которой вы просите, никогда не существовала. Если вы хотите создать его вручную, но нет ничего такого, что вы могли бы проверить. Слияние никоим образом не объединяет в себе какую-то объединенную историю. Если ваш вопрос «как мне вручную создать такую историю», задайте ее. Но вы, похоже, уже знаете, как использовать rebase.
Я думаю, что ваше основное недоразумение может быть результатом вывода git-log. Порядок коммитов показан git log по сути произвольным выбором. История не линейна, но она должна перечислять их один за другим, так и есть. Этот порядок не означает, что один коммит является родительским для предыдущего, и, следовательно, это не означает, что если вы выберете один из этих коммитов, под ним будет напечатано объединение всего. Он может распечатывать списки коммитов, как вы указали в своем вопросе, но в вашем примере репозитория это выглядит как история Вы можете увидеть это с gitk --all
или git log --graph
.
1 - 2 - 3 - 4 - 5 - 6 - 7 (another-branch)
\ \
A - B - C - D - --------M (master)
Вот и все. Слияние не волшебным образом соединяет эти ветви. Он создает один коммит, чьи родители являются объединенными коммитами, содержащий комбинацию содержимого объединенных коммитов. Таким образом, вы можете проверить коммит 2 или коммит B, но «коммит 2 в основной ветке» отсутствует. Вы можете, если хотите, проверить коммит B и объединить коммит 2 и посмотреть, что вы получите.
Список коммитов, которые вы говорите, что вы хотите, насколько я могу судить, это то, что вы получили бы, объединив коммиты 5 и B, и сгладив их произвольным образом. Если вы просто хотите получить результат слияния:
git checkout -b foo <commit-5>
git merge <commit-B>
Если вам на самом деле нужна плоская история:
git checkout -b foo <commit-5>
git rebase -i <commit-B>
# reorder them however it is you wanted them
Но это все пользовательские решения. Вы создаете состояние хранилища, которого никогда не было. Так как его никогда не было, вы должны его создать.
Что касается обсуждения хэшей в комментариях, опять же, SHA1 однозначно идентифицирует коммит. SHA1 для коммита 2 - это SHA1 только для этого коммита. Вы не доказали, что я не прав в своем тестовом репо, вы доказали, что я прав: там только один коммит 2 и у него только один хэш.
Коммит - это объект, содержащий несколько вещей: метаданные (имя автора / коммиттера, адрес электронной почты, дата; сообщение о коммите), ссылку на его родительский (ые) объект и дерево, которое он представляет (воспринимайте его как снимок содержимое). Таким образом, commit 2 представляет этот конкретный снимок. Ни больше ни меньше. Его родитель - коммит 1. Это не вопрос временных меток; коммит знает своих родителей по их SHA1. Родитель коммита 2 - коммит 1, несмотря ни на что. Существует только один коммит 2, независимо от того, достигли ли вы его из основной ветви или из другой ветви - посмотрите на рисунок, и вы увидите, как он находится в основной ветви, через 7, 6, 5, 4, 3.