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, у вас есть два варианта.
после использования
git reset HEAD~перейдите через патчи по отдельности с помощьюgit add -pчтобы выбрать те, которые вы хотите в каждой фиксацииотредактируйте рабочую копию, чтобы удалить изменения, которые вы не хотите; зафиксируйте это промежуточное состояние; а затем верните полную фиксацию для следующего раунда.
опция 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-страница имеет именно то, что вы хотите:
обратите внимание, что есть также
git reset --soft HEAD^. Это похоже наgit reset(по умолчанию--mixed), но он сохраняет содержимое индекса. Так что если вы добавили/удалили файлы, они уже есть в индексе.оказывается очень полезным в случае гигантских совершает.
теперь в последнем TortoiseGit на Windows вы можете сделать это очень легко.
откройте диалоговое окно rebase,настроить, и выполните следующие действия.
- щелкните правой кнопкой мыши фиксацию, которую вы хотите разделить, и выберите"
Edit" (среди пик, сквош, удалить...).- нажмите "
Start" для начала перебазирования.- как только он прибывает в коммит для разделения, проверьте "" и нажмите на кнопку"
Amend" напрямую. Диалог фиксации открытие.![]()
- снимите выделение с файлов, которые вы хотите поместить в отдельную фиксацию.
- измените сообщение фиксации и нажмите кнопку"
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