Программно исправить последнюю фиксацию в предыдущей

Каждый раз, когда я хочу исправить свою последнюю фиксацию во вторую последнюю фиксацию, я делаю это

git rebase HEAD~2 -i
<replace pick with fixup on line 2>

Есть ли способ сделать это в автоматизированном скрипте без вмешательства человека?

Я пробовал это, и это не работает:

git commit --fixup=HEAD

person iBug    schedule 16.04.2018    source источник
comment
Возможный дубликат Как запустить git rebase - -интерактивный неинтерактивным способом?   -  person phd    schedule 16.04.2018
comment
@phd Не совсем, это другой вопрос, который можно решить разными способами.   -  person iBug    schedule 16.04.2018


Ответы (4)


git reset HEAD~1 --soft
git commit --amend --no-edit

or

git reset HEAD~2 --soft
git commit -C ORIG_HEAD^ --reset-author 

or

head=`git log -1 --pretty=%H HEAD~1`
git reset HEAD~2 --hard
git merge --squash ORIG_HEAD
git commit -C $head --reset-author

or

head=`git log -1 --pretty=%h HEAD~1`
git reset HEAD~2 --hard
git cherry-pick -n HEAD..ORIG_HEAD
git commit -C $head --reset-author

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

Обновление: объяснение второго:

Предположим, у нас есть A-B-C в качестве последних трех коммитов, а C — головной. Что вы хотите, так это сжать B и C в один коммит, который повторно использует сообщение коммита B.

git reset HEAD~2 --soft сбрасывает HEAD в A и сохраняет изменения B и C в индексе и в рабочем дереве. Затем следующий git commit создает фиксацию, которая включает изменения в индексе, также известные как изменения B и C.

Как следует из названия, ORIG_HEAD указывает на исходную головку, в данном случае на ту, что была до последнего сброса, то есть C. И ORIG_HEAD^ означает первого родителя ORIG_HEAD, то есть B. -C ORIG_HEAD^ означает повторное использование сообщения фиксации B без редактирования.

Подробнее о --soft, -C и --reset-author.

person ElpieKay    schedule 16.04.2018
comment
Не могли бы вы немного пояснить второй? Это выглядит полезным, но я немного смущен. - person iBug; 16.04.2018
comment
@iBug Рад, что это помогает. - person ElpieKay; 16.04.2018

Каждый раз, когда я хочу исправить свою последнюю фиксацию,

Это можно сделать напрямую:

git commit --amend

Для старых коммитов:

git commit --fixup $commit
git rebase HEAD~n -i --autosquash

Это автоматически интерпретирует префиксы fixup!, сгенерированные ранее --fixup (или вручную).

person user1686    schedule 16.04.2018
comment
Я думаю, что неправильно написал вопрос. Я хочу исправить (раздавить, но отказаться от сообщения фиксации) последнюю фиксацию в предыдущей. - person iBug; 16.04.2018
comment
Не делайте фиксацию в первую очередь, --amend предыдущую. - person user1686; 16.04.2018

Я все еще ищу «каноническое» решение с самим Git.

Вот мое временное решение обходного пути:

EDITOR="sed -i "2s/pick/fixup/'" git rebase -i HEAD~2

По сути, просто заменил интерактивный текстовый редактор на sed.

person iBug    schedule 16.04.2018

Кажется, это работает для меня, полностью автоматически и не требует какой-либо конкретной ша или чего-то еще:

git commit -a --fixup HEAD ; GIT_SEQUENCE_EDITOR=touch git rebase --interactive --autosquash HEAD~2
person JAR.JAR.beans    schedule 14.05.2019