Как объединить два коммита в один, если я уже начал перебазирование?

Я пытаюсь объединить 2 коммита в 1, поэтому я последовал "давя совершает с перебазироваться" из Git готов.

я побежал

git rebase --interactive HEAD~2

в появившемся редакторе, я меняю pick to squash а затем save-quit, но rebase терпит неудачу с ошибкой

невозможно "раздавить" без предыдущей фиксации

теперь, когда мое дерево работы достигло этого состояния, у меня возникли проблемы с восстановлением. Команда git rebase --interactive HEAD~2 не с

интерактивная перебаза уже началась

и git rebase --continue выдает

невозможно "раздавить" без предыдущей фиксации

11 ответов


резюме

сообщение об ошибке

невозможно "раздавить" без предыдущей фиксации

означает, что вы, вероятно, пытались " раздавить вниз."ГИТ всегда патиссоны новый коммит в старой совершения или "вверх", как показано в интерактивном списке задач перебазирования, то есть в фиксацию в предыдущей строке. Изменение команды в первой строке списка задач на squash всегда будет производить эту ошибку как есть ничего для первой попытки.

Исправления

сначала вернитесь туда, откуда вы начали с

$ git rebase --abort

скажите, что ваша история

$ git log --pretty=oneline
a931ac7c808e2471b22b5bd20f0cad046b1c5d0d c
b76d157d507e819d7511132bdb5a80dd421d854f b
df239176e1a2ffac927d8b496ea00d5488481db5 a

то есть a был первым коммитом, затем b и, наконец, c. После совершения c мы решаем раздавить b и c вместе:

(Примечание: Работает git log трубы его выход на пейджер, less по умолчанию на большинстве платформ. Выйти из пейджера и вернуться к в командной строке нажмите q ключ.)

под управлением git rebase --interactive HEAD~2 дает вам редактор с

pick b76d157 b
pick a931ac7 c

# Rebase df23917..a931ac7 onto df23917
#
# 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's log message
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

(обратите внимание, что этот список в обратном порядке по сравнению с выходом git log.)

изменение b pick to squash приведет к ошибке, которую вы видели, но если вместо этого вы раздавите c в b (более новая фиксация в более старую или "раздавливание вверх"), изменив список задач на

pick   b76d157 b
squash a931ac7 c

и Save-уход Редактор, вы получите другой редактор, содержимое которого

# This is a combination of 2 commits.
# The first commit's message is:

b

# This is the 2nd commit message:

c

когда вы сохраняете и выходите, содержимое отредактированного файла становится сообщением фиксации нового комбинированного фиксации:

$ git log --pretty=oneline
18fd73d3ce748f2a58d1b566c03dd9dafe0b6b4f b and c
df239176e1a2ffac927d8b496ea00d5488481db5 a

Примечание О Переписывании Истории

Interactive rebase переписывает историю. Попытка нажать на пульт, содержащий старую историю, завершится неудачей, потому что это не перемотка вперед.

если ветку вы перебазируется это тема или ветка , в котором вы работаете в одиночку ничего страшного. Для нажатия на другой репозиторий потребуется --force опция, или альтернативно вы можете, в зависимости от разрешений удаленного репозитория, сначала удалить старую ветвь, а затем нажать rebased версию. Примеры тех команд, которые потенциально могут уничтожить работу, выходят за рамки этого ответа.

уже опубликованные переписывание истории на ветке, в которой вы работаете с другими людьми без очень хорошая причина, такая как утечка пароля или других чувствительных деталей, заставляет работать на ваших сотрудников и является антисоциальной и будет раздражать других разработчиков. The "восстановление из раздела" Перемещение "вверх" в git rebase документация объясняет, с дополнительным акцентом.

перебазирование (или любая другая форма перезаписи) ветви, на которой другие основывают работу, - плохая идея: любой, кто ниже по течению, вынужден вручную исправить свою историю. В этом разделе объясняется, как сделать исправление с точки зрения нисходящего потока. реальное исправление, однако, было бы избежать перезагрузки вверх по течению в первую очередь. ...


Если есть несколько коммитов, вы можете использовать git rebase -i чтобы раздавить два коммита в один.

Если есть только два коммита, которые вы хотите объединить, и они являются "последними двумя", следующие команды могут быть использованы для объединения двух коммитов в один:

git reset --soft "HEAD^"
git commit --amend

Rebase: вам это не понадобится:

простой способ для наиболее частого сценария.

в большинстве случаев:

на самом деле, если все, что вы хотите, это просто просто объединить несколько последних коммитов в один но не нужно drop, reword и другая работа rebase.

вы можете просто сделать:

git reset --soft "HEAD~n"
  • предполагая, что ~n - это количество коммитов, чтобы мягко отменить фиксацию (т. е. ~1, ~2,...)

затем используйте следующую команду для изменения сообщения фиксации.

git commit --amend

что довольно такой же, как длинный ряд squash и pick.

и он работает для n коммитов, но не только для двух коммитов, как указано выше.


сначала вы должны проверить, сколько совершает у вас есть:

git log

есть два состояния:

что есть только два коммита:

например:

commit A
commit B

(в этом случае вы не можете использовать git rebase) вам нужно сделать следующее.

$ git reset --soft HEAD^1

$ git commit --amend

другое заключается в том, что существует более двух коммитов; вы хотите объединить commit C и D.

например:

commit A
commit B
commit C
commit D

(под этим условие, вы можете использовать git rebase)

git rebase -i B

и чем использовать "сквош" делать. Редеет остальное очень легко. Если вы все еще не знаете, пожалуйста, прочитайтеhttp://zerodie.github.io/blog/2012/01/19/git-rebase-i/


предполагая, что вы были в вашей собственной теме ветки. Если вы хотите объединить последние 2 коммита в один и выглядеть как герой, отделитесь от коммита непосредственно перед тем, как вы сделали последние два коммита.

git checkout -b temp_branch HEAD^2

затем squash совершает другую ветвь в этой новой ветви:

git merge branch_with_two_commits --squash

это принесет изменения, но не зафиксирует их. Так что просто соверши их,и все.

git commit -m "my message"

Теперь вы можете объединить эту новую ветку обратно в основную ветку.


вы можете отменить перебазироваться с

git rebase --abort

и когда вы снова запускаете интерактивную команду rebase, ' squash; commit должен быть ниже фиксации выбора в списке


Я часто использую git reset --mixed чтобы вернуть базовую версию до нескольких коммитов, которые вы хотите объединить, тогда я сделаю новый коммит, таким образом, ваш коммит новейший, убедитесь, что ваша версия HEAD после нажатия на сервер.

commit ac72a4308ba70cc42aace47509a5e
Author: <me@me.com>
Date:   Tue Jun 11 10:23:07 2013 +0500

    Added algorithms for Cosine-similarity

commit 77df2a40e53136c7a2d58fd847372
Author: <me@me.com>
Date:   Tue Jun 11 13:02:14 2013 -0700

    Set stage for similar objects

commit 249cf9392da197573a17c8426c282
Author: Ralph <ralph@me.com>
Date:   Thu Jun 13 16:44:12 2013 -0700

    Fixed a bug in space world automation

если я хочу объединить два коммита в один, сначала я использую:

git reset --mixed 249cf9392da197573a17c8426c282

"249cf9392da197573a17c8426c282" была третьей версией, также ваша базовая версия перед слиянием, после этого я делаю новый commit:

git add .
git commit -m 'some commit message'

Это все, надеюсь, это еще один способ для всех.

к твоему сведению, из git reset --help:

 --mixed
     Resets the index but not the working tree (i.e., the changed files are
     preserved but not marked for commit) and reports what has not been
     updated. This is the default action.

$ git rebase --abort

запустите этот код в любое время, если вы хотите отменить git rebase

$ git rebase -i HEAD~2

повторно применить последние два коммита. Эта команда откроет редактор кода

  • [ последняя фиксация будет внизу ]. Изменить последнее совершите сквош(ы). Поскольку сквош будет сливаться с предыдущим коммитом.
  • затем нажмите клавишу esc и введите: wq для сохранения и закрытия

после :wq вы будете в активном режиме перебазировать

Примечание: вы получите другой редактор, если нет предупреждений / сообщений об ошибках, если есть ошибка или предупреждение другой редактор не будет отображаться, вы можете прервать выполнение $ git rebase --abort Если вы видите ошибку или предупреждение, просто продолжайте работать $ git rebase --continue

вы увидите 2 коммита. Выберите один или напишите собственное сообщение фиксации, сохраните и закройте [: wq]

Примечание. 2: вам может потребоваться принудительно перенести изменения в удаленное РЕПО, если вы запустите команду rebase

$ git push -f

$ git push -f origin master


если ваша главная ветвь git log выглядит примерно так:

commit ac72a4308ba70cc42aace47509a5e
Author: <me@me.com>
Date:   Tue Jun 11 10:23:07 2013 +0500

    Added algorithms for Cosine-similarity

commit 77df2a40e53136c7a2d58fd847372
Author: <me@me.com>
Date:   Tue Jun 11 13:02:14 2013 -0700

    Set stage for similar objects

commit 249cf9392da197573a17c8426c282
Author: Ralph <ralph@me.com>
Date:   Thu Jun 13 16:44:12 2013 -0700

    Fixed a bug in space world automation

и вы хотите объединить два верхних коммита, просто выполните следующие простые шаги:

  1. во-первых, чтобы быть на безопасной стороне проверки второй последней фиксации в отдельной ветке. Вы можете назвать филиал как угодно. git checkout 77df2a40e53136c7a2d58fd847372 -b merged-commits
  2. теперь просто выберите изменения из последнего коммита в эту новую ветку как:git cherry-pick -n -x ac72a4308ba70cc42aace47509a5e. (Разрешить конфликты, если они возникают)
  3. Итак, ваш изменения в последней фиксации есть во второй последней фиксации. Но вы все равно должны совершить, поэтому сначала добавьте изменения, которые вы просто выбрали, а затем выполните git commit --amend.

вот и все. Вы можете нажать эту объединенную версию в ветке "merged-commits", если хотите.

кроме того, вы можете отказаться от двух коммитов спина к спине в главной ветви. Просто обновите свою главную ветку как:

git checkout master
git reset --hard origin/master (CAUTION: This command will remove any local changes to your master branch)
git pull

С git cherry-pick для почти всего, для меня это естественно делать даже здесь.

учитывая, что у меня есть branchX проверено, и есть два коммита на его кончике, из которых я хочу создать один коммит, объединяющий их содержимое, я делаю это:

git checkout HEAD^ // Checkout the privious commit
git cherry-pick --no-commit branchX // Cherry pick the content of the second commit
git commit --amend // Create a new commit with their combined content

если я хочу обновить branchX также (и я полагаю, что это обратная сторона этого метода) я также должен:

git checkout branchX
git reset --hard <the_new_commit>

Если вы хотите объединить два последних коммита и просто использовать сообщение старого коммита, вы можете автоматизировать процесс с помощью expect.

Я предполагаю, что:

  • вы используете vi в качестве редактора
  • ваши коммиты являются однострочными каждый

Я тестировал с git version 2.14.3 (Apple Git-98).


#!/usr/bin/env expect
spawn git rebase -i HEAD~2

# down, delete word, insert 's' (for squash), Escape, save and quit
send "jdwis 3:wq\r"

expect "# This is a"

# down 4, delete 3 lines, save and quit
send "4j3d\r:wq\r"

interact