Короткий ответ: нет, вы не можете этого сделать. Вы можете сделать то, что может достаточно.
История - только коммит. Коммиты являются историей.
Каждый коммит имеет свой уникальный хэш-идентификатор. Этот хэш-идентификатор является фиксацией в очень реальном смысле, хотя технически это криптографическая контрольная сумма содержимого этой фиксации. Содержимое включает в себя идентификатор хэша сохраненного исходного снимка и идентификатор хэша непосредственно предыдущей фиксации. Это то, что позволяет Git начинать с последнего коммита и работать в обратном направлении, по одному коммиту за раз, через цепочку коммитов: commit Z
имеет родительский хеш Y
, поэтому Git может найти Y
и посмотрите, что у него есть родительский хэш X
и т. д.
Коммиты слияния являются особенными только одним способом: они имеют более одного родительского хэша. (Обычно их ровно два; более двух - это слияние осьминога , и они на самом деле не достигают ничего, чего нельзя было бы сделать несколькими отдельными слияниями, хотя они полезны для демонстрации того, что цель объединение состояло в том, чтобы связать кучу ревизий одновременно, и, конечно, для демонстрации своего Git-fu. :-)) При коммите слияния Git будет следовать обе истории , если вы не скажете это не (см. ниже).
Как вы видели, git merge
работает, следуя истории - обратной цепочке коммитов - обратно к общему коммиту. У вас либо есть коммиты, и они являются общими; или у вас их нет, так что делать нечего. Затем, для обычного git merge
, он делает коммит слияния, помня обоих непосредственных предшественников, что делает возможным будущие слияния. Использование git merge --squash
обрезает дополнительного родителя, что - по крайней мере потенциально, а часто и практически - делает гораздо более трудным слияние в будущем, поскольку вы получаете древнего предка вместо желаемого современного.
Что вы можете делать
Обычно git log
следует за историей - за все истории - путем обхода графика коммитов, один шаг за раз, назад:
...--o--o--o--o <-- branch (HEAD)
Когда история линейная (без слияний), это работает нормально, но когда слияние имеет:
o---------o-------o
/ \
...--o--o *--o--o <-- branch (HEAD)
\ /
o--o--o--o--o--o--o
Git будет следовать обеим веткам слияния *
, которые он выполняет по одному коммиту за раз. Но вы можете сказать, чтобы этого не делали :
git log --first-parent
Эта опция --first-parent
сообщает Git, что когда он встречает коммит слияния, такой как *
выше, он должен смотреть только на первого родителя слияния.
Какой родитель является первым родителем? Ответ таков: первым родителем слияния является коммит, который был текущий коммит, когда вы сделали слияние. Так что в этом случае у нас было:
o---------o-------o <-- branch (HEAD)
/
...--o--o
\
o--o--o--o--o--o--o <-- other
до вы бежали git merge
. Вы пробежали git checkout branch
, чтобы войти в это состояние. Затем вы запустили git merge other
, чтобы сделать коммит слияния *
. Таким образом, первый родительский коммит *
- это коммит в верхнем ряду, который вы использовали при запуске git merge
.
Таким образом, git log --first-parent
вообще не будет показывать нижний ряд коммитов. Они по-прежнему будут присутствовать, часть истории, позволяя будущим слияниям работать хорошо и, конечно, также увеличивать ваш репозиторий, но вы не будете видеть их.
Огромное количество git log
аргументов о невидимости конкретных коммитов: отсеивание деревьев, чтобы вы могли видеть лес. Например, git log --simplify-by-decoration
пропускает показ любых коммитов, которые не имеют название ветви или тега. Используя git log [--follow] -- <path>
, вы говорите Git не показывать коммиты, что не изменяет данный файл или поддерево. Существуют и другие варианты, влияющие на то, как работает «упрощение истории», и они становятся довольно сложными. Вы можете изучить справочную страницу git log
в течение нескольких дней. Но начните с --first-parent
.