Git rebase неинтерактивен для последних двух коммитов - напишите командный файл

Помогите, пожалуйста, написать пакетный файл для git rebase, объединяющий два последних коммита: HEAD и HEAD~1 в текущей ветке в один без использования интерактивного редактора.

Предположим, что оба коммита имеют одного родителя и еще не отправлены.

a683ec1 Not pushed 2
c7b480a Not pushed 1
f0e81fb Pushed

Я хочу оставить коммит «Pushed» и один коммит, который будет содержать «Not push 1» + «Not push 2» в конечном состоянии «Not push 2».


person Paul    schedule 30.05.2014    source источник
comment
Вам действительно нужен пакет (.bat или .cmd для интерпретации с помощью cmd.exe) или подойдет любой скрипт? Git всегда требует оболочки POSIX, даже в Windows, и это гораздо более приятная среда для сценариев.   -  person Jan Hudec    schedule 30.05.2014
comment
Собираетесь ли вы написать сообщение фиксации вручную, предоставить короткое сообщение фиксации в качестве аргумента, использовать сообщение первой фиксации, использовать сообщение второй фиксации или объединить сообщения фиксации (обработка сообщения фиксации кажется наиболее сложной частью процедуры, на самом деле ).   -  person Jan Hudec    schedule 30.05.2014
comment
Возможный дубликат Есть ли способ раздавить ряд коммитов не в интерактивном режиме?   -  person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 18.07.2016


Ответы (1)


Идея заключалась бы в том, чтобы сделать:

git reset --soft @~ # reset HEAD, preserve current working tree and index
git commit --amend -m "squash HEAD and HEAD~"

Однако это не относится к сообщениям фиксации: сообщение из ORIG_HEAD будет потеряно.
torek обращается к этому в комментариях.

Если у вас есть несколько коммитов для сквоша (начиная с origin/master), вы можете сделать следующее (предположим, что у вас нет незавершенной работы):

echo "squash everything since origin/master" > /tmp/msg
git log  --format=%B origin/master~3.. >> /tmp/msg
git reset --soft origin/master
git commit -F /tmp/msg

На этот раз вы не изменяете коммит, на который вы сбросили (поскольку origin/master уже был отправлен), а создаете новый.

person VonC    schedule 30.05.2014
comment
Разве git reset --hard не теряет коммиты? Исправление лучше, чем перебазирование? - person Paul; 30.05.2014
comment
@Paul Я отредактировал ответ: я хочу сохранить текущее рабочее дерево, но сбросить индекс и HEAD на HEAD~. Затем я добавляю все и исправляю текущий коммит, оставляя HEAD~ (теперь новый HEAD) со всеми изменениями, которые были в ORIG_HEAD. - person VonC; 30.05.2014
comment
Спасибо за скрипт, работает, но с одной проблемой: Работает только с первого раза. Если я выполняю этот пакет повторно, я ожидаю, что в git log --oneline будет на один коммит меньше, но я вижу тот же измененный коммит и коммит перед ним. (Да, есть более двух коммитов перед отправкой одного). - person Paul; 30.05.2014
comment
@Paul, странно, учитывая, что HEAD всегда сбрасывается на HEAD~ - person VonC; 30.05.2014
comment
@Paul Да, есть более двух коммитов перед отправкой одного: вы можете сбросить HEAD на HEAD~n, где n — это количество коммитов для сквоша. Таким образом, нет необходимости повторять сценарий. - person VonC; 30.05.2014
comment
На самом деле было бы проще сохранить индекс. Поскольку git add -A может добавить вещи, которые не были версионированы в ORIG_HEAD. - person Jan Hudec; 30.05.2014
comment
@VonC: да, я могу это сделать, могу перечислить git log и подсчитать комментарии вручную, но хотел бы иметь простой в использовании пакетный файл с как можно меньшим количеством входных параметров. В идеале — с одним параметром — комментарий. Затем я мог бы выполнять его снова и снова, пока не дойду до желаемой фиксации. - person Paul; 30.05.2014
comment
@Paul, зачем считать коммиты вручную? На то, что было отправлено, ссылается origin/master. Я отредактировал свой ответ, чтобы избежать этого. - person VonC; 30.05.2014
comment
@JanHudec действительно. В этом случае я не думаю, что git add нужен. - person VonC; 30.05.2014
comment
@VonC: Действительно, git add не нужен. И не желанный. - person Jan Hudec; 30.05.2014
comment
Кроме того, вы можете собрать все исходные сообщения журнала коммитов, которые нужно раздавить, используя git log origin/master.. перед выполнением git reset --soft (добавьте любое желаемое форматирование). Сохраните во временный файл, используйте в качестве шаблона или сообщения для нового коммита. - person torek; 30.05.2014