Главная Категории Контакты Поиск

git autosquash

Как можно использовать git autosquash для автоматизации очистки своей ветки.

Git·18.07.2019·читать 4 мин 🤓·Автор: Alexey Myzgin

Предположим, что мы работаем в ветке и хотим быстро внести пару изменений, поэтому мы постоянно фиксируем эти изменения, делая коммит сообщения. Конечно, в конце концов, мы можем сделать interactive rebase, чтобы снова очистить нашу историю и объединить её. Однако, мы также можем автоматизировать эти шаги, используя флаг fixup.

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

git add .

git commit -m 'update README'

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

Очевидно, мы можем сделать git rebase и очистить нашу историю, после того как всё доделаем. Но, поскольку мы уже знаем, что коммиты должны быть объединены в конкретный комит, можем выполнить это заранее.

Сначала, как обычно, делаем git add ., добавляя файл в промежуточную область; затем делаем git commit --fixup и передаем идентификатор сообщения коммита, к которому он должен позже автоматически присоединиться.

git add .

git commit --fixup f3247e1

Если мы выполним git log, то увидим, что у нас есть update README, а затем fixup! update README.

* 1d9b62a - (HEAD -> app-refactoring) fixup! update README (5 seconds ago) <Oleksii Myzgin>
* f3247e1 - update README (17 minutes ago) <Oleksii Myzgin>
* 74708e6 - (origin/master, master) add title (4 days ago) <Oleksii Myzgin>

Давай сделаем ещё несколько изменений в README. Затем, делаем git add ., и git commit --fixup точно так же, как мы делали это раньше. Но вместо того, чтобы указывать идентификатор, мы можем указать поиск везде где есть текст update в сообщении коммита, и применить исправление по верх него. В этом случае, он возьмет последний коммит и установит его поверх другого, который мы создали ранее.

git add .

git commit --fixup :/update

Выполнив комманду git log, можем видеть, что у нас есть первое исправление, а затем ещё одно поверх него.

* 65ab96a - (HEAD -> app-refactoring) fixup! fixup! update README (8 seconds ago) <Oleksii Myzgin>
* 1d9b62a - fixup! update README (9 minutes ago) <Oleksii Myzgin>

* f3247e1 - update README (26 minutes ago) <Oleksii Myzgin>
* 74708e6 - (origin/master, master) add title (4 days ago) <Oleksii Myzgin>

В то же время, можем не продолжать работу над README, а переходить в другой файл. После, снова возобновляем нашу работу над README. Если мы хотим чтобы этот коммит был поверх update README, можем снова использовать git add ., а затем git commit --fixup :/update:

git add .

git commit --fixup :/update

Теперь git lоg выглядит так:

* 679d6d6 - (HEAD -> app-refactoring) fixup! fixup! fixup! update README (76 seconds ago) <Oleksii Myzgin>
* fcf000c - add app footer (7 minutes ago) <Oleksii Myzgin>
* 65ab96a - fixup! fixup! update README (13 minutes ago) <Oleksii Myzgin>
* 1d9b62a - fixup! update README (22 minutes ago) <Oleksii Myzgin>

* f3247e1 - update README (39 minutes ago) <Oleksii Myzgin>
* 74708e6 - (origin/master, master) add title (4 days ago) <Oleksii Myzgin>

Нам нужно автоматически очистить всё, вплоть до коммита здесь 74708e6.

Можем сделать интерактивный git rebase, вместе с autosquash, до этой точки.

git rebase -i --autosquash 74708e6

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

pick f3247e1 update README
fixup 1d9b62a fixup! update README
fixup 65ab96a fixup! fixup! update README
fixup 679d6d6 fixup! fixup! fixup! update README
pick fcf000c add app footer

# Rebase 74708e6..679d6d6 onto 74708e6 (5 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .       create a merge commit using the original merge commit's
# .       message (or the oneline, if no original merge commit was
# .       specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

Давай сохраним все - :wq. Если сейчас мы сделаем git log, то увидим, что наша история была очищена автоматически.

* 38e8211 - (HEAD -> app-refactoring) add app footer (4 seconds ago) <Oleksii Myzgin>
* d13b462 - update README (4 seconds ago) <Oleksii Myzgin>

* 74708e6 - add title (4 days ago) <Oleksii Myzgin>

Website, name & logo
Copyright © 2022. Alex Myzgin