Выполнение ребаза «Пробного запуска» серии патчей StGit
Мне не очень понравился мой предыдущий ответ, потому что он использовал reset --hard
в основной ветке. Вот рабочий процесс, который использует временную ветвь для предварительного просмотра перебазирования, чтобы увидеть, сколько работы он включает. Если это окажется тривиальным, вы позволите этой ветке заменить вашу основную ветвь, как совет «Мастера ситхов» из стр. 25-26 из Git From The Bottom Up .
Если в ребазе есть масса конфликтов, и вы хотите отложить сортировку до более удобного времени, вы просто переключаетесь обратно на ветку master
и продолжаете работать, удаляя временную ветку.
Начальное условие
Предположим, у вас есть рабочее дерево, созданное с помощью stg clone
, которое содержит стек патчей, все из которых в настоящее время применяются:
evadeflow@GILGAMESH /c/d/projects/luasand_stg (master)
$ stg series
+ add-copyright-notice
+ add-bn-namespace
> fix-tabs
Вы обновляете свою удаленную ссылку на репозиторий, из которого вы клонировали, и видите, что произошли некоторые изменения:
evadeflow@GILGAMESH /c/d/projects/luasand_stg (master)
$ git remote update
Fetching origin
remote: Counting objects: 9, done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 5 (delta 4), reused 0 (delta 0)
Unpacking objects: 100% (5/5), done.
From c:/d/projects/luasand
b22d65f..ab55ba3 master -> origin/master
Вы думаете: «Я бы хотел быть как можно более актуальным, но я не уверен, что хочу сейчас разобраться с этим ...» Что делать?
Экспорт серии исправлений
Первое, что нужно сделать - выписать серию патчей, чтобы ее можно было импортировать во временную ветку, созданную на следующем шаге:
evadeflow@GILGAMESH /c/d/projects/luasand_stg (master)
$ stg export --dir=/f/projects/luasand_stg_patches
Checking for changes in the working directory ... done
evadeflow@GILGAMESH /c/d/projects/luasand_stg (master)
$ ls /f/projects/luasand_stg_patches
add-bn-namespace add-copyright-notice fix-tabs series
(Существует способ перенести исправления без их экспорта, но я предпочитаю делать это так, потому что они служат резервной копией.)
Создать временную ветку
Затем создайте временную ветку, чтобы просмотреть ребаз. Единственная сложность в этом - выбор базовой ревизии для ветвления. Есть несколько способов сделать это, но я предпочитаю вставлять все патчи и ветки следующим образом:
evadeflow@GILGAMESH /c/d/projects/luasand_stg (master)
$ stg pop --all
Popped fix-tabs -- add-copyright-notice
No patch applied
evadeflow@GILGAMESH /c/d/projects/luasand_stg (master)
$ stg branch --create rbtemp
Checking for changes in the working directory ... done
Recording as a local branch
Branch "rbtemp" created
(Опять же, есть и другие способы сделать это, но я считаю это самым простым.)
Импорт патчей на временную ветку
Следующая команда, которую вы хотите выполнить:
evadeflow@GILGAMESH /c/d/projects/luasand_stg (rbtemp)
$ stg import -s /f/projects/luasand_stg_patches/series
Checking for changes in the working directory ... done
Importing patch "add-copyright-notice" ... done
Importing patch "add-bn-namespace" ... done
Importing patch "fix-tabs" ... done
Now at patch "fix-tabs"
Конечным результатом является то, что ветка rbtemp
выглядит точно так же, как ваша ветка master
до того, как вы начали.
Выполнить ребазу
Наконец, вы можете выполнить ребаз во временной ветке. Команда для этого:
evadeflow@GILGAMESH /c/d/projects/luasand_stg (rbtemp)
$ stg rebase remotes/origin/master
[Output omitted]
Есть несколько способов, которыми это может оказаться, и я сейчас подробно опишу:
Rebase: Путь Дождливого Дня
Поскольку это был мотив для моего первоначального вопроса, я начну со случая, когда в перебазе есть конфликты, с которыми вы не хотите иметь дело в данный момент. Вот как выглядит этот сценарий:
evade@GILGAMESH /c/d/projects/luasand_stg (rbtemp)
$ stg rebase remotes/origin/master
Checking for changes in the working directory ... done
Popping all applied patches ... done
Rebasing to "remotes/origin/master" ... done
Pushing patch "add-copyright-notice" ...
CONFLICT (content): Merge conflict in Variant.h
CONFLICT (content): Merge conflict in main.cpp
Error: The merge failed during "push".
Revert the operation with "stg undo".
stg rebase: 2 conflict(s)
Если вы находитесь в центре чего-то, от чего вы не хотите, чтобы вас отстранили, и вам не хотелось бы сейчас исправлять эти конфликты, просто сделайте следующее:
evadeflow@GILGAMESH /c/d/projects/luasand_stg (rbtemp)
$ stg reset --hard
evadeflow@GILGAMESH /c/d/projects/luasand_stg (rbtemp)
$ stg branch master
Checking for changes in the working directory ... done
Switching to branch "master" ... done
evadeflow@GILGAMESH /c/d/projects/luasand_stg (master)
$ stg branch --delete --force rbtemp
Deleting branch "rbtemp" ... done
evadeflow@GILGAMESH /c/d/projects/luasand_stg (master)
$ stg push --all
Pushing patch "add-copyright-notice" ... done (unmodified)
Pushing patch "add-bn-namespace" ... done (unmodified)
Pushing patch "fix-tabs" ... done (unmodified)
Now at patch "fix-tabs"
Теперь вы вернулись к тому, с чего начали, и можете запланировать перебазировку на более удобное время.
Rebase: Путь облачного дня
Если у перебазировки есть несколько конфликтов, которые выглядят управляемыми, вы можете решить их сортировать прямо в тот момент в вашей временной ветке. Я представлю, как выглядит этот процесс, включая несколько ошибок, которые я сделал по пути (то есть, забыл сделать git add --update
):
evade@GILGAMESH /c/d/projects/luasand_stg (rbtemp)
$ stg rebase remotes/origin/master
Checking for changes in the working directory ... done
Popping all applied patches ... done
Rebasing to "remotes/origin/master" ... done
Pushing patch "add-copyright-notice" ...
CONFLICT (content): Merge conflict in Variant.h
CONFLICT (content): Merge conflict in main.cpp
Error: The merge failed during "push".
Revert the operation with "stg undo".
stg rebase: 2 conflict(s)
evadeflow@GILGAMESH /c/d/projects/luasand_stg (rbtemp)
$ vim Variant.h main.cpp
evadeflow@GILGAMESH /c/d/projects/luasand_stg (rbtemp)
$ git add --update
evadeflow@GILGAMESH /c/d/projects/luasand_stg (rbtemp)
$ stg refresh
Now at patch "add-copyright-notice"
evadeflow@GILGAMESH /c/d/projects/luasand_stg (rbtemp)
$ stg series
> add-copyright-notice
- add-bn-namespace
- fix-tabs
evadeflow@GILGAMESH /c/d/projects/luasand_stg (rbtemp)
$ stg push --all
Pushing patch "add-bn-namespace" ... done (conflict)
Error: 1 merge conflict(s)
CONFLICT (content): Merge conflict in main.cpp
Now at patch "add-bn-namespace"
evadeflow@GILGAMESH /c/d/projects/luasand_stg (rbtemp)
$ vim main.cpp
evadeflow@GILGAMESH /c/d/projects/luasand_stg (rbtemp)
$ stg push --all
stg push: Worktree not clean. Use "refresh" or "status --reset"
evadeflow@GILGAMESH /c/d/projects/luasand_stg (rbtemp)
$ stg refresh
stg refresh: Cannot refresh -- resolve conflicts first
evadeflow@GILGAMESH /c/d/projects/luasand_stg (rbtemp)
$ git add --update
evadeflow@GILGAMESH /c/d/projects/luasand_stg (rbtemp)
$ stg refresh
Now at patch "add-bn-namespace"
evadeflow@GILGAMESH /c/d/projects/luasand_stg (rbtemp)
$ stg push --all
Pushing patch "fix-tabs" ... done (empty)
Now at patch "fix-tabs"
evadeflow@GILGAMESH /c/d/projects/luasand_stg (rbtemp)
$ stg series
+ add-copyright-notice
+ add-bn-namespace
> fix-tabs
Команда `` stg push --all` останавливается после каждого неуспешного патча, что дает вам возможность исправить его. По сути, вы продолжаете пытаться протолкнуть все патчи, пока не очистите их. После этого ваш стек патчей снова станет чистым, и он станет последним вышестоящим выпуском. Вы запускаете свои тесты, и они все проходят. Woot!
Единственная проблема: вы проделали всю работу над rbtemp
. Так как все прошло хорошо, вам бы очень хотелось, чтобы это было в вашей основной ветке. Не проблема. Просто переименуйте rbtemp
в master и удалите старую ветку master:
evadeflow@GILGAMESH /c/d/projects/luasand_stg (rbtemp)
$ stg branch --rename master old_master
fatal: No such section!
Upgraded branch old_master to format version 2
Renamed branch "master" to "old_master"
evadeflow@GILGAMESH /c/d/projects/luasand_stg (rbtemp)
$ stg branch old_master
Checking for changes in the working directory ... done
Switching to branch "old_master" ... done
evadeflow@GILGAMESH /c/d/projects/luasand_stg (old_master)
$ stg branch --rename rbtemp master
fatal: No such section!
Upgraded branch master to format version 2
Renamed branch "rbtemp" to "master"
evadeflow@GILGAMESH /c/d/projects/luasand_stg (old_master)
$ stg branch master
Checking for changes in the working directory ... done
Switching to branch "master" ... done
evadeflow@GILGAMESH /c/d/projects/luasand_stg (master)
$ stg branch --delete --force old_master
Deleting branch "old_master" ... done
evadeflow@GILGAMESH /c/d/projects/luasand_stg (master)
$
И вот вы сидите на своей master
ветке, готовые продолжить работу. (Примечание: я не уверен, что означают ошибки fatal: No such section!
. Я некоторое время полностью игнорировал эту ошибку без каких-либо побочных эффектов.)
Rebase: Солнечный день Путь
Последний сценарий, который следует рассмотреть, - это когда ваши исправления применяются корректно, без конфликтов, к последней вышестоящей версии.Вот как будет выглядеть вывод rebase
в этом случае:
evadeflow@GILGAMESH /c/d/projects/luasand_stg (rbtemp)
$ stg rebase remotes/origin/master
Checking for changes in the working directory ... done
Popping all applied patches ... done
Rebasing to "remotes/origin/master" ... done
Pushing patch "add-copyright-notice" ... done
Pushing patch "add-bn-namespace" ... done (modified)
Pushing patch "fix-tabs" ... done
Now at patch "fix-tabs"
Если вы запустите свои тесты, и они все пройдут, тогда вы просто выполните совет 'Sith Master', обозначенный в конце 'Cloudy'Раздел «Путь дня» выше, чтобы переименовать rbtemp
в master
и удалить старую ветку master.
Summary
Если вы еще не очень хорошо знаете git и по крайней мере некоторое знакомство с StGit, описанные выше шаги могут показаться ужасно сложными.Они не.Это займет немного времени, чтобы привыкнуть к такой работе.Это не для всех, но если вам нужно поддерживать сложный набор патчей для чужой кодовой базы, это довольно эффективно по сравнению с любыми альтернативами, которые я знаю.(Пожалуйста, прокомментируйте, если у вас есть стратегия, которую вы считаете проще; я всегда стремлюсь улучшить свой рабочий процесс.)
Я не всегда стараюсь создать временную ветку для предварительного просмотра перебазирования.Иногда я просто пробую сначала master
и делаю stg reset --hard
, если есть конфликты - что не очень часто.Мне нравится сортировка по временной ветке, когда возникают конфликты.Это дает мне определенное спокойствие, зная, что я очень маловероятно, чтобы свернуть свою основную ветвь, в то время как я пытаюсь отменить свою серию патчей.