Как я сквошу два не последовательных фиксации?
Я немного новичок во всей функции перезагрузки в git. Скажем, что я сделал следующие коммиты:
A -> B -> C -> D
Впоследствии я понимаю, что D
содержит исправление, которое зависит от некоторого нового кода, добавленного в A
, и что эти коммиты принадлежат друг другу. Как склеить A
и D
вместе и оставить только B
и C
?
Ответы
Ответ 1
Вы можете запустить git rebase --interactive
и переупорядочить D до B и раздавить D в A.
Git откроет редактор, и вы увидите такой файл:
pick aaaaaaa Commit A
pick bbbbbbb Commit B
pick ccccccc Commit C
pick ddddddd Commit D
# Rebase aaaaaaa..ddddddd onto 1234567 (4 command(s))
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit log message
# x, exec = run command (the rest of the line) using shell
#
# 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
Теперь вы измените файл так, чтобы он выглядел следующим образом:
pick aaaaaaa Commit A
squash ddddddd Commit D
pick bbbbbbb Commit B
pick ccccccc Commit C
И теперь git объединит изменения A и D в один коммит, а затем поместит B и C. Если вы не хотите сохранять сообщение коммита D, вы также можете использовать ключевое слово "fixup".
Ответ 2
Примечание. Вы должны не изменять фиксации, которые были нажаты, на другое репо, если вы не знаете последствия .
git log --oneline -4
D commit_message_for_D
C commit_message_for_C
B commit_message_for_B
A commit_message_for_A
git rebase --interactive
pick D commit_message_for_D
pick C commit_message_for_C
pick B commit_message_for_B
pick A commit_message_for_A
Введите i
(поместите VIM в режим вставки)
Измените список, чтобы он выглядел следующим образом (вам не нужно удалять или включать сообщение фиксации). Не пропустите squash
!:
pick C commit_message_for_C
pick B commit_message_for_B
pick A commit_message_for_A
squash D
Введите Esc, затем ZZ
(Сохранить и выйти из VIM)
# This is a combination of 2 commits.
# The first commit message is:
commit_message_for_D
# This is the 2nd commit message:
commit_message_for_A
Введите i
Измените текст на то, что вы хотите, чтобы новое сообщение фиксации выглядело. Я рекомендую это описание изменений в commit A
и D
:
new_commit_message_for_A_and_D
Введите Esc, затем ZZ
git log --oneline -4
E new_commit_message_for_A_and_D
C commit_message_for_C
B commit_message_for_B
git show E
(You should see a diff showing a combination of changes from A and D)
Теперь вы создали новый commit E
. Commits A
и D
больше не находятся в вашей истории, но не исчезли. Вы можете восстановить их в этот момент и некоторое время git rebase --hard D
(git rebase --hard
уничтожит любые локальные изменения!).
Ответ 3
Для тех, кто использует SourceTree:
Убедитесь, что вы еще не нажали на фиксации.
- Репозиторий > Интерактивная ребаза...
- Перетащите D (новый фиксатор) непосредственно над A (старший коммит)
- Убедитесь, что выделена команда D.
- Нажмите
Squash with previous
Ответ 4
Интерактивная перебазировка работает хорошо, пока у вас не появится большая ветка функций с 20-30 коммитами и/или парой слияний от мастера или/и исправлением конфликтов, пока вы коммитили в своей ветке. Даже с поиском моих коммитов по истории и заменой pick
на squash
здесь не получалось. Поэтому я искал другой путь и нашел эту статью. Я сделал свои изменения, чтобы работать над этим на отдельной ветке:
git checkout master
git fetch
git pull
git merge branch-name
git reset origin/master
git branch -D branch-name
git checkout -b branch-name
git add --all
#Do some commit
git push -f --set-upstream origin branch-name
До этого я получил свой запрос на получение с ~ 30 коммитами с 2-3 слияниями от master + исправление конфликтов. И после этого я получил четкий пиар с одним коммитом.
PS вот скрипт bash для выполнения этих шагов в автоматическом режиме.
Ответ 5
$git мастер проверки
$git log --oneline
D
C
B
A
$git rebase --onto HEAD ^^^ HEAD ^
$git log --oneline
D
A