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

Я пытаюсь объединить 2 коммита в 1, поэтому я последовал за "squashing commits with rebase" из git ready.

Я побежал

git rebase --interactive HEAD~2

В результирующем редакторе я меняю pick на squash, а затем сохраняю-выхожу, но сбой ошибки с ошибкой

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

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

Интерактивная перезагрузка уже запущена

и git rebase --continue сбой

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

Ответы

Ответ 1

Резюме

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

Не может "сквош" без предыдущего коммита

означает, что вы, вероятно, пытались "раздавить вниз". Git всегда сдавливает новый коммит в более старый коммит или "вверх", как это видно в интерактивном списке задач перебазирования, то есть в коммит в предыдущей строке. Изменение команды в ваших списках задач в самой первой строке для 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 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.)

Изменение bs pick на squash приведет к squash ошибке, но если вместо этого вы нажмете c на b (более новый коммит на более старый или "сдвинет вверх"), изменив список задач на

pick   b76d157 b
squash a931ac7 c

и сохранить выход из редактора, вы получите другой редактор, содержимое которого

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

b

# This is the 2nd commit message:

c

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

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

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

Интерактивный ребаз переписывает историю. Попытка передать на удаленный компьютер, который содержит старую историю, потерпит неудачу, потому что это не перемотка вперед.

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

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

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

Ответ 2

Если есть несколько коммитов, вы можете использовать git rebase -i для сквоша двух коммитов в один.

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

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

Ответ 3

Rebase: Вам это не нужно:

Более простой способ для наиболее частых сценариев.

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

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

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

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

Затем используйте следующую команду, чтобы изменить сообщение коммита.

git commit --amend

это почти то же самое, что длинный squash и один pick.

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

Ответ 4

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

git log

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

Во-первых, существует только: две коммиты:

Например:

commit A
commit B

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

$ git reset --soft HEAD^1

$ git commit --amend

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

Например:

commit A
commit B
commit C
commit D

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

git rebase -i B

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

Ответ 5

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

git checkout -b temp_branch HEAD^2

Затем squash передайте другую ветку в этой новой ветке:

git merge branch_with_two_commits --squash

Это приведет к изменениям, но не приведет к их фиксации. Так что просто передайте их, и все готово.

git commit -m "my message"

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

Ответ 6

вы можете отменить rebase с помощью

git rebase --abort

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

Ответ 7

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

commit ac72a4308ba70cc42aace47509a5e
Author: <[email protected]>
Date:   Tue Jun 11 10:23:07 2013 +0500

    Added algorithms for Cosine-similarity

commit 77df2a40e53136c7a2d58fd847372
Author: <[email protected]>
Date:   Tue Jun 11 13:02:14 2013 -0700

    Set stage for similar objects

commit 249cf9392da197573a17c8426c282
Author: Ralph <[email protected]>
Date:   Thu Jun 13 16:44:12 2013 -0700

    Fixed a bug in space world automation

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

git reset --mixed 249cf9392da197573a17c8426c282

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

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

Все, надежда - это еще один способ для всех.

FYI, от 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.

Ответ 8

$ git rebase --abort

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

$ git rebase -i HEAD~2

Повторное использование последних двух коммитов. Вышеприведенная команда откроет редактор кода

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

После: wq вы будете в активном режиме восстановления

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

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

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

$ git push -f

$ git push -f origin master

Ответ 9

Так как я использую 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>

Ответ 10

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

commit ac72a4308ba70cc42aace47509a5e
Author: <[email protected]>
Date:   Tue Jun 11 10:23:07 2013 +0500

    Added algorithms for Cosine-similarity

commit 77df2a40e53136c7a2d58fd847372
Author: <[email protected]>
Date:   Tue Jun 11 13:02:14 2013 -0700

    Set stage for similar objects

commit 249cf9392da197573a17c8426c282
Author: Ralph <[email protected]>
Date:   Thu Jun 13 16:44:12 2013 -0700

    Fixed a bug in space world automation

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

  • Сначала, чтобы быть в безопасной стороне, второй последний фиксатор в отдельной ветке. Вы можете назвать ветку чем угодно. git checkout 77df2a40e53136c7a2d58fd847372 -b merged-commits
  • Теперь просто вишня - выберите свои изменения из последнего фиксации в эту новую ветку как: git cherry-pick -n -x ac72a4308ba70cc42aace47509a5e. (Устраняйте конфликты, если они возникнут)
  • Итак, теперь ваши изменения в последнем фиксации присутствуют в вашей второй последней фиксации. Но вам все равно придется совершать, поэтому сначала добавьте изменения, которые вы только выбрали, а затем выполните 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

Ответ 11

Если вы хотите объединить два последних коммита и просто использовать старое сообщение о коммите, вы можете автоматизировать процесс, используя 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 \033:wq\r"

expect "# This is a"

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

interact