Разбить предыдущую фиксацию на несколько коммитов



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

1024   11  
git

11 ответов:

git rebase -i сделаем это.

во-первых, начните с чистого рабочего каталога: git status не ожидающих изменений, удалений или добавлений.

чтобы разделить ваш последний коммит, сначала:

$ git reset HEAD~

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

если он был дальше в дереве, то

$ git rebase -i HEAD~3

здесь 3 сколько совершает назад она есть.

если он был дальше в дереве, Чем вы хотите посчитать, то

$ git rebase -i 123abcd~

здесь 123abcd - это SHA1 коммита, который вы хотите разделить.

когда вы получите экран редактирования rebase, найдите фиксацию, которую вы хотите разбить. В начале этой строки замените pick С edit (e для краткости). Сохраните буфер и выйдите. Rebase теперь остановится сразу после фиксации, которую вы хотите изменить. Затем:

$ git reset HEAD~

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

$ git rebase --continue

С git-rebase руководство (раздел коммитов разделения)

в интерактивном режиме вы можете отметить фиксации с помощью действия "редактировать". Однако это не обязательно означает, что git rebase ожидает, что результат этого редактирования будет точно одним фиксатором. Действительно, Вы можете отменить фиксацию или добавить другие фиксации. Это можно использовать для разделения фиксации на две части:

  • начните интерактивную перебазировку с git rebase -i <commit>^, где <commit> это фиксация вы хотите разделить. Фактически, любой диапазон фиксации будет делать, пока он содержит эту фиксацию.

  • отметьте фиксацию, которую вы хотите разделить с помощью действия "редактировать".

  • когда дело доходит до редактирования, совершить, выполнить git reset HEAD^. Эффект заключается в том, что голова перематывается на один, и индекс следует этому примеру. Однако, рабочее дерево остается прежним.

  • теперь добавьте изменения в индекс, который вы хотите иметь в первый коммит. Вы можете использовать git add (возможно, в интерактивном режиме) или git gui (или оба), чтобы сделать это.

  • зафиксируйте теперь текущий индекс с любым сообщением фиксации, которое подходит сейчас.

  • повторите последние два шага, пока ваше рабочее дерево не станет чистым.

  • продолжить перебазирование с git rebase --continue.

использовать git rebase --interactive чтобы изменить эту предыдущую фиксацию, запустите git reset HEAD~, а потом git add -p чтобы добавить некоторые, затем сделать коммит, а затем добавить еще несколько и сделать еще один коммит, столько раз, сколько вам нравится. Когда закончишь, беги git rebase --continue, и у вас будут все разделенные коммиты ранее в вашем стеке.

важно: обратите внимание, что вы можете играть вокруг и сделать все изменения, которые вы хотите, и не придется беспокоиться о потере старых изменений, потому что вы всегда можете запустить git reflog найти точку в проекте, который содержит изменения, которые вы хотите, (назовем его a8c4ab), а затем git reset a8c4ab.

вот несколько команд, чтобы показать, как это работает:

mkdir git-test; cd git-test; git init

теперь добавьте файл A

vi A

добавьте следующую строку:

one

git commit -am one

затем добавьте эту строку в A:

two

git commit -am two

затем добавить этот строку:

three

git commit -am three

теперь файл A выглядит так:

one
two
three

и наш git log выглядит следующим образом (Ну, я использую git log --pretty=oneline --pretty="%h %cn %cr ---- %s"

bfb8e46 Rose Perrone 4 seconds ago ---- three
2b613bc Rose Perrone 14 seconds ago ---- two
9aac58f Rose Perrone 24 seconds ago ---- one

допустим, мы хотим разделить второй коммит, two.

git rebase --interactive HEAD~2

это вызывает сообщение, которое выглядит следующим образом:

pick 2b613bc two
pick bfb8e46 three

изменить pick до e редактировать, что совершать.

git reset HEAD~

git diff показывает нам, что мы только что не выполнили коммит, который мы сделали для второго коммита:

diff --git a/A b/A
index 5626abf..814f4a4 100644
--- a/A
+++ b/A
@@ -1 +1,2 @@
 one
+two

давайте поставим это изменение и добавим "и третий" к этой строке в файле A.

git add .

обычно это точка во время интерактивной перебазировки, где мы будем запускать git rebase --continue, потому что обычно мы просто хотим вернуться в наш стек обязуется изменить ранее совершал. Но на этот раз, мы хотим создайте новую фиксацию. Так что мы побежим git commit -am 'two and a third'. Теперь мы редактируем файл A и добавить строку two and two thirds.

git add . git commit -am 'two and two thirds' git rebase --continue

у нас конфликт с нашим совершал, three, так что давайте решать ее:

мы изменим

one
<<<<<<< HEAD
two and a third
two and two thirds
=======
two
three
>>>>>>> bfb8e46... three

до

one
two and a third
two and two thirds
three

git add .; git rebase --continue

теперь наш!--42--> выглядит так:

commit e59ca35bae8360439823d66d459238779e5b4892
Author: Rose Perrone <[email protected]>
Date:   Sun Jul 7 13:57:00 2013 -0700

    three

diff --git a/A b/A
index 5aef867..dd8fb63 100644
--- a/A
+++ b/A
@@ -1,3 +1,4 @@
 one
 two and a third
 two and two thirds
+three

commit 4a283ba9bf83ef664541b467acdd0bb4d770ab8e
Author: Rose Perrone <[email protected]>
Date:   Sun Jul 7 14:07:07 2013 -0700

    two and two thirds

diff --git a/A b/A
index 575010a..5aef867 100644
--- a/A
+++ b/A
@@ -1,2 +1,3 @@
 one
 two and a third
+two and two thirds

commit 704d323ca1bc7c45ed8b1714d924adcdc83dfa44
Author: Rose Perrone <[email protected]>
Date:   Sun Jul 7 14:06:40 2013 -0700

    two and a third

diff --git a/A b/A
index 5626abf..575010a 100644
--- a/A
+++ b/A
@@ -1 +1,2 @@
 one
+two and a third

commit 9aac58f3893488ec643fecab3c85f5a2f481586f
Author: Rose Perrone <[email protected]>
Date:   Sun Jul 7 13:56:40 2013 -0700

    one

diff --git a/A b/A
new file mode 100644
index 0000000..5626abf
--- /dev/null
+++ b/A
@@ -0,0 +1 @@
+one

предыдущие ответы охватывали использование git rebase -i чтобы изменить фиксацию, которую вы хотите разделить, и зафиксировать ее по частям.

это хорошо работает при разделении файлов на разные коммиты, но если вы хотите разбить изменения на отдельные файлы, вам нужно знать больше.

добравшись до фиксации, которую вы хотите разделить, используя rebase -i и пометить его для edit, у вас есть два варианта.

  1. после использования git reset HEAD~ перейдите через патчи по отдельности с помощью git add -p чтобы выбрать те, которые вы хотите в каждой фиксации

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

опция 2 полезна, если вы разделяете большую фиксацию, так как она позволяет проверить, что промежуточные версии строятся и работают правильно как часть слияния. Это продолжается как следует.

после использования rebase -i и editing фиксации, используйте

git reset --soft HEAD~

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

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

как только вы будете счастливы, этап / unstage файлы по мере необходимости (мне нравится использовать git gui для этого), и зафиксировать изменения с помощью пользовательского интерфейса или командной строки

git commit

это первое совершенное коммит. Теперь вы хотите восстановить свою рабочую копию в состояние, которое она имела после фиксации, которую вы разделяете, так что вы можете принять больше изменений для вашего следующего фиксации. Чтобы найти sha1 коммита, который вы редактируете, используйте git status. В первых нескольких строках состояния вы увидите команду rebase, которая в настоящее время выполняется, в которой вы можете найти sha1 вашей исходной фиксации:

$ git status
interactive rebase in progress; onto be83b41
Last commands done (3 commands done):
   pick 4847406 US135756: add debugging to the file download code
   e 65dfb6a US135756: write data and download from remote
  (see more in file .git/rebase-merge/done)
...

в этом случае фиксация, которую я редактирую, имеет sha1 65dfb6a. Зная это, я могу проверить содержимое этого коммита по моему рабочему каталогу, используя форму git checkout который принимает как фиксацию, так и расположение файла. Здесь я использую . как расположение файла для замены всей рабочей копии:

git checkout 65dfb6a .

не пропустите точку на конце!

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

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

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

git commit --file .git/rebase-merge/message

наконец, как только вы совершите все изменения,

git rebase --continue

продолжит и завершит операцию перебазирования.

git rebase --interactive может использоваться для разделения коммита на меньшие коммиты. Элемент документы Git для перебазирования есть краткое описание процесса - расщепления совершает:

в интерактивном режиме вы можете отметить фиксации с помощью действия "редактировать". Однако, это не обязательно означает, что git rebase ожидает, что результатом этого изменения будет ровно один коммит. Действительно, Вы можете отменить фиксацию или добавить другие фиксации. Это можно использовать для разделения фиксации на два:

  • начните интерактивную перебазировку с git rebase -i <commit>^, где <commit> это фиксация, которую вы хотите разделить. Фактически, любой диапазон фиксации будет делать, пока он содержит эту фиксацию.

  • отметьте фиксацию, которую вы хотите разделить с помощью действия "редактировать".

  • когда дело доходит до редактирования, совершить, выполнить git reset HEAD^. Эффект заключается в том, что голова перематывается на один, и индекс следует этому примеру. Тем не менее, рабочее дерево остается прежним.

  • теперь добавьте изменения в индекс, который вы хотите иметь в первой фиксации. Вы можете использовать git add (возможно, в интерактивном режиме) или Git gui (или оба), чтобы сделать это.

  • зафиксируйте теперь текущий индекс с любым сообщением фиксации, которое подходит сейчас.

  • повторите последние два шага, пока ваше рабочее дерево не станет чистым.

  • продолжить перебазирование с помощью git rebase --continue.

если вы не совсем уверены, что промежуточные версии непротиворечивы (они компилируются, проходят testsuite и т. д.) вы должны использовать git stash чтобы спрятать еще не зафиксированные изменения после каждой фиксации, протестируйте и измените фиксацию, если необходимы исправления.

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

http://git-scm.com/docs/git-rebase#_splitting_commits

обратите внимание, что есть также git reset --soft HEAD^. Это похоже на git reset (по умолчанию --mixed), но он сохраняет содержимое индекса. Так что если вы добавили/удалили файлы, они уже есть в индексе.

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

теперь в последнем TortoiseGit на Windows вы можете сделать это очень легко.

откройте диалоговое окно rebase,настроить, и выполните следующие действия.

  • щелкните правой кнопкой мыши фиксацию, которую вы хотите разделить, и выберите"Edit" (среди пик, сквош, удалить...).
  • нажмите "Start" для начала перебазирования.
  • как только он прибывает в коммит для разделения, проверьте "" и нажмите на кнопку"Amend" напрямую. Диалог фиксации открытие.
    Edit/Split commit
  • снимите выделение с файлов, которые вы хотите поместить в отдельную фиксацию.
  • измените сообщение фиксации и нажмите кнопку"commit".
  • пока не появятся файлы для фиксации, диалог фиксации будет открываться снова и снова. Когда больше нет файла для фиксации, он все равно спросит вас, Хотите ли вы добавить еще один фиксатор.

очень полезно, спасибо TortoiseGit !

Я думаю, что лучший способ я использую git rebase -i. Я создал видео, чтобы показать шаги для разделения фиксации:https://www.youtube.com/watch?v=3EzOz7e1ADI

самое простое, что можно сделать без интерактивной перебазировки,- это (вероятно) сделать новую ветвь, начиная с фиксации до того, как вы хотите разделить, cherry-pick-N фиксация, сброс, тайник, фиксация перемещения файла, повторное применение тайника и фиксация изменений, а затем либо слияние с предыдущей ветвью, либо вишневый выбор последующих коммитов. (Затем переключите прежнее имя ветви на текущую головку.) (Вероятно, лучше следовать советам MBO и делать интерактивную перебазировку.)

если у вас есть это:

A - B <- mybranch

где вы совершили некоторый контент в commit B:

/modules/a/file1
/modules/a/file2
/modules/b/file3
/modules/b/file4

но вы хотите разделить B на C-D, и получить этот результат:

A - C - D <-mybranch

вы можете разделить содержимое, например, так (содержимое из разных каталогов в разных коммитах)...

сброс ветви обратно в фиксацию перед тем, как разделить:

git checkout mybranch
git reset --hard A

создать первый коммит (C):

git checkout B /modules/a
git add -u
git commit -m "content of /modules/a"

создать второй commit (D):

git checkout B /modules/b
git add -u
git commit -m "content of /modules/b"

Comments

    Ничего не найдено.