Как я могу объединить два коммита в один, если я уже начал ребаз? - PullRequest
1091 голосов
/ 02 апреля 2010

Я пытаюсь объединить 2 коммита в 1, поэтому я следовал & ldquo; сжатие коммитов с rebase & rdquo; из мерзавца готов .

Я побежал

git rebase --interactive HEAD~2

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

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

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

Интерактивный ребаз уже начался

и git rebase --continue завершаются с

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

Ответы [ 11 ]

1662 голосов
/ 02 апреля 2010

Резюме

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

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

означает, что вы, вероятно, пытались «раздавить вниз». 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'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's pick на squash приведет к ошибке, которую вы видели, но если вместо этого вы нажмете c на b (новый коммит на более старый или «сдвинуть вверх»), изменив список задач на

pick   b76d157 b
squash a931ac7 c

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

# 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

Примечание об истории перезаписи

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

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

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

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

379 голосов
/ 11 июля 2014

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

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

git reset --soft "HEAD^"
git commit --amend
84 голосов
/ 26 апреля 2017

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

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

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

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

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

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

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

git commit --amend

, что в значительной степени совпадает с длинным диапазоном squash и одним pick.

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

52 голосов
/ 27 мая 2014

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

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

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

28 голосов
/ 24 октября 2013

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

git checkout -b temp_branch HEAD^2

Затем сквош коммит другой ветке в этой новой ветке:

git merge branch_with_two_commits --squash

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

git commit -m "my message"

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

22 голосов
/ 02 апреля 2010

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

git rebase --abort

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

16 голосов
/ 09 сентября 2013

Я часто использую 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" была третьей версией, также является вашей базовой версией до слияния, после чего я делаю новый коммит:

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.
11 голосов
/ 21 февраля 2017

$ 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

2 голосов
/ 26 ноября 2015

Поскольку я использую 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>
1 голос
/ 06 февраля 2018

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