Как разбить последний коммит на два в Git
У меня есть две рабочие ветки, мастер и форум, и я только что внесли некоторые изменения в ветку forum, что мне бы хотелось to cherry-pick в master. Но, к сожалению, фиксация, которую я хочу использовать для вишни, также содержит некоторые изменения, которые мне не нужны.
Решение, вероятно, состояло бы в том, чтобы каким-то образом удалить неправильную фиксацию и заменить ее двумя отдельными коммитами, с изменениями, которые я хочу выбрать в master, и другими, которые там не принадлежат.
Я пробовал делать
git reset --hard HEAD^
который удалил все изменения, поэтому мне пришлось вернуться с помощью
git reset ORIG_HEAD
Итак, мой вопрос: как лучше всего разделить последнее коммит на два отдельных коммита?
Ответы
Ответ 1
Вы должны использовать индекс. После выполнения смешанного reset ( " git reset HEAD ^" ) добавьте
первый набор изменений в индекс, а затем зафиксировать их. Затем зафиксируйте
остальное.
Вы можете использовать git добавить", чтобы внести все изменения, сделанные в файл в индекс. если ты
не хотят ставить каждую модификацию, сделанную в файле, только некоторые из них, вы
может использовать "git add -p" .
Посмотрим на пример. Предположим, что у меня есть файл с именем myfile, который содержит
следующий текст:
something
something else
something again
Я изменил его в своем последнем коммите, чтобы теперь он выглядел следующим образом:
1
something
something else
something again
2
Теперь я решил, что хочу разбить его на две части, и я хочу, чтобы
первая строка должна быть в первом фиксации, а вставка последней строки
во второй фиксации.
Сначала я возвращаюсь к родительскому элементу HEAD, но я хочу сохранить изменения в файловой системе,
поэтому я использую "git reset" без аргумента (который будет делать так называемый "смешанный" )
reset):
$ git reset HEAD^
myfile: locally modified
$ cat myfile
1
something
something else
something again
2
Теперь я использую "git add -p" , чтобы добавить изменения, которые я хочу зафиксировать для индекса (= I
этап их). "git add -p" - это интерактивный инструмент, который спрашивает вас о том, что
изменения в файл должны быть добавлены в индекс.
$ git add -p myfile
diff --git a/myfile b/myfile
index 93db4cb..2f113ce 100644
--- a/myfile
+++ b/myfile
@@ -1,3 +1,5 @@
+1
something
something else
something again
+2
Stage this hunk [y,n,a,d,/,s,e,?]? s # split this section into two!
Split into 2 hunks.
@@ -1,3 +1,4 @@
+1
something
something else
something again
Stage this hunk [y,n,a,d,/,j,J,g,e,?]? y # yes, I want to stage this
@@ -1,3 +2,4 @@
something
something else
something again
+2
Stage this hunk [y,n,a,d,/,K,g,e,?]? n # no, I don't want to stage this
Затем я фиксирую это первое изменение:
$ git commit -m "Added first line"
[master cef3d4e] Added first line
1 files changed, 1 insertions(+), 0 deletions(-)
Теперь я могу выполнить все остальные изменения (а именно цифру "2", помещенную в последнюю строку):
$ git commit -am "Added last line"
[master 5e284e6] Added last line
1 files changed, 1 insertions(+), 0 deletions(-)
Позвольте проверить журнал, чтобы узнать, что у нас есть:
$ git log -p -n2 | cat
Commit 5e284e652f5e05a47ad8883d9f59ed9817be59d8
Author: ...
Date: ...
Added last line
Diff --git a/myfile b/myfile
Index f9e1a67..2f113ce 100644
--- a/myfile
+++ b/myfile
@@ -2,3 +2,4 @@
something
something else
something again
+2
Commit cef3d4e0298dd5d279a911440bb72d39410e7898
Author: ...
Date: ...
Added first line
Diff --git a/myfile b/myfile
Index 93db4cb..f9e1a67 100644
--- a/myfile
+++ b/myfile
@@ -1,3 +1,4 @@
+1
something
something else
something again
Ответ 2
Цели:
- Я хочу разделить прошлое commit (
splitme
) на два.
- Я хочу сохранить сообщение фиксации.
План:
- перезагрузите интерактивный интерфейс от одного до
splitme
.
- изменить
splitme
.
- Reset файлы для разделения на вторую фиксацию.
- Изменить фиксацию, сохранить сообщение, при необходимости изменить.
- Добавить обратно файлы, разделенные с первого коммита.
- Зафиксировать новое сообщение.
- Продолжить перезагрузку.
Шаги восстановления (1 и 7) могут быть пропущены, если splitme
является последним фиксатором.
git rebase -i splitme^
# mark splitme commit with 'e'
git reset HEAD^ -- $files
git commit --amend
git add $files
git commit -m "commit with just some files"
git rebase --continue
Если бы я хотел, чтобы сплит файлы были первыми записаны, я бы снова перезаписал -i и переключил порядок
git rebase -i splitme^
# swap order of splitme and 'just some files'
Ответ 3
Чтобы изменить текущую фиксацию на две коммиты, вы можете сделать что-то вроде следующего.
Или:
git reset --soft HEAD^
Это отменяет последнее коммит, но оставляет все поставленным. Затем вы можете отключить определенные файлы:
git reset -- file.file
По желанию вы можете отремонтировать части этих файлов:
git add -p file.file
Сделайте новый первый фиксатор:
git commit
Сцена и фиксация остальных изменений во второй фиксации:
git commit -a
Или:
Отменить и отключить все изменения от последнего фиксации:
git reset HEAD^
Выборочно выполните первый раунд изменений:
git add -p
Commit:
git commit
Завершите остальные изменения:
git commit -a
(В любом случае, если вы отменили фиксацию, которая добавила новый файл и хотите добавить это ко второй фиксации, вам придется вручную добавить ее как commit -a
только этапы изменения уже отслеженных файлов.)
Ответ 4
Запустите git gui
, выберите переключатель "Изменить последнюю фиксацию" и измените нестационарность (Commit > Unstage From Commit или Ctrl - U), которые вы не хотите вступать в первую фиксацию. Я думаю, что это самый простой способ сделать это.
Еще одна вещь, которую вы можете сделать, - это выбрать вишню без фиксации (git cherry-pick -n
), а затем вручную или с помощью git gui
выбрать необходимые изменения перед фиксацией.
Ответ 5
git reset HEAD^
the -hard - это то, что убивает ваши изменения.
Ответ 6
Я удивлен, что никто не предложил git cherry-pick -n forum
. Это приведет к изменениям от последней forum
фиксации, но не приведет к их фиксации - вы можете reset
отменить изменения, которые вам не нужны, и зафиксировать то, что вы хотите сохранить.
Ответ 7
Метод double-revert-squash
- Сделайте еще одну фиксацию, которая удалит ненужные изменения. (Если это файл, это очень просто:
git checkout HEAD~1 -- files with unwanted changes
и git commit
. Если нет, файлы со смешанными изменениями могут быть частично поставлены git reset file
и git add -p file
в качестве промежуточного шага.) Назовите это возвратом.
-
git revert HEAD
- Сделайте еще одну фиксацию, которая добавит лишние изменения. Это двойной возврат
- Из двух коммитов, которые вы сейчас сделали, сквойте первый на фиксацию для разделения (
git rebase -i HEAD~3
). Эта фиксация теперь освобождается от нежелательных изменений, поскольку они находятся во второй фиксации.
Преимущества
- Сохраняет сообщение о фиксации
- Работает, даже если фиксация для разделения не является последней. Это требует только того, чтобы нежелательные изменения не конфликтуют с последующими коммитами