Вы должны использовать git rebase --onto
и указать диапазон.
(см. git rebase
справочную страницу :
трансплантируйте ветку темы на основе одной ветки в другую, чтобы сделать вид, что вы разветвили ветку темы из последней ветки, используя rebase --onto
.
).
Конечно, это переместит вашу ветку bug10
поверх ветки legacy
, а это не то, что вам нужно / нужно.
Таким образом, одним из обходных путей было бы сделать эту перебазировку в клонированном репо, а затем объединить эту «улучшенную» legacy
ветку (ту, что в репозитории клонов, с модификациями bug10
сверху из этого) в локальную и текущую legacy
ветку (ту, которую вы хотите изменить, оставив bug10
в покое).
Сейчас:
- это включает в себя дополнительное репо (что может привести к ограничению дискового пространства)
- В целом, это довольно эквивалентно определить патч и применить его к
legacy
ветви, поэтому остальные ответы (патч) являются действительными (и более простыми).
- единственное преимущество, которое я вижу в этом методе, - это возможность определить унаследованную среду, в которой вы перебазируете то, что хотите (например, коммиты
bug10
), прежде чем помещать только эту ветку legacy
в исходное репо (вы бы не нажимайте bug10
, поскольку его история была бы полностью переписана!)
Я просто хотел посмотреть, работает ли он, так что ... Давайте проверим этот подход.
(Git1.6.5.1, на старой версии XP SP2, с сеансом Powershell 1.0 из-за команды Start-Transcript
)
PS D:\> mkdir git
PS D:\> cd git
PS D:\git> mkdir tests
PS D:\git> cd tests
PS D:\git\tests> git init mainRepo
Мне нравится, что у меня больше нет возможности сначала создать каталог git repo, а затем ввести его git init
! С 1.6.5 :
"git init
" научился mkdir
/ chdir
помещать в каталог при наличии дополнительного аргумента (т. Е. "git init this
").
Это здорово!
Давайте создадим 3 файла для 3 разных целей.
(Для примера, я буду хранить модификации файлов отдельно для каждой ветви: здесь нет конфликтов при слиянии или перебазировании.)
PS D:\git\tests> cd mainRepo
PS D:\git\tests\mainRepo> echo mainFile > mainFile.txt
PS D:\git\tests\mainRepo> echo contentToBeFixed > toBeFixedFile.txt
PS D:\git\tests\mainRepo> echo legacyContent > legacy.txt
PS D:\git\tests\mainRepo> git add -A
PS D:\git\tests\mainRepo> git ci -m "first commit"
PS D:\git\tests\mainRepo> echo firstMainEvol >> mainFile.txt
PS D:\git\tests\mainRepo> git ci -a -m "first evol, for making 1.0"
PS D:\git\tests\mainRepo> git tag -m "1.0 legacy content" 1.0
В этот момент возвращается git log --graph --oneline --branches
:
* b68c1f5 first evol, for making 1.0
* 93f9f7c first commit
Давайте построим legacy
ветку
PS D:\git\tests\mainRepo> git co -b legacy
PS D:\git\tests\mainRepo> echo aFirstLegacyEvol >> legacy.txt
PS D:\git\tests\mainRepo> git ci -a -m "a first legacy evolution"
Мы возвращаемся к мастеру, делаем еще один коммит, который мы будем помечать "2.0" (релиз, который потребует исправления ошибок!)
PS D:\git\tests\mainRepo> git co -b master
PS D:\git\tests\mainRepo> git co master
PS D:\git\tests\mainRepo> echo aMainEvol >> mainFile.txt
PS D:\git\tests\mainRepo> git ci -a -m "a main evol"
PS D:\git\tests\mainRepo> echo aSecondMainEvolFor2.0 >> mainFile.txt
PS D:\git\tests\mainRepo> git ci -a -m "a second evol for 2.0"
PS D:\git\tests\mainRepo> git tag -m "main 2.0 before bugfix" 2.0
У нас есть:
* e727105 a second evol for 2.0
* 473d44e a main evol
| * dbcc7aa a first legacy evolution
|/
* b68c1f5 first evol, for making 1.0
* 93f9f7c first commit
Теперь мы делаем bug10
ветку для исправления ошибок:
PS D:\git\tests\mainRepo> git co -b bug10
PS D:\git\tests\mainRepo> echo aFirstBug10Fix >> toBeFixedFile.txt
PS D:\git\tests\mainRepo> git ci -a -m "a first bug10 fix"
PS D:\git\tests\mainRepo> echo aSecondBug10Fix >> toBeFixedFile.txt
PS D:\git\tests\mainRepo> git ci -a -m "a second bug10 fix"
Давайте добавим окончательный коммит в основную ветку
PS D:\git\tests\mainRepo> git co master
PS D:\git\tests\mainRepo> echo anotherMainEvol >> mainFile.txt
PS D:\git\tests\mainRepo> git ci -a -m "another main evol"
Конечное состояние нашего основного репо:
* 55aac85 another main evol
| * 47e6ee1 a second bug10 fix
| * 8183707 a first bug10 fix
|/
* e727105 a second evol for 2.0
* 473d44e a main evol
| * dbcc7aa a first legacy evolution
|/
* b68c1f5 first evol, for making 1.0
* 93f9f7c first commit
На этом этапе я не буду больше манипулировать в mainRepo. Я только клонирую это, чтобы сделать некоторые тесты. Если это не удается, я всегда могу вернуться к этому репо и клонировать его снова.
Первый клон на самом деле обязателен, чтобы выполнить наш git rebase --onto
PS D:\git\tests\mainRepo> cd ..
PS D:\git\tests> git clone mainRepo rebaseRepo
PS D:\git\tests> cd rebaseRepo
Нам нужны две ветви mainRepo в нашем клонированном репо:
PS D:\git\tests\rebaseRepo> git co -b bug10 origin/bug10
PS D:\git\tests\rebaseRepo> git co -b legacy origin/legacy
Давайте перебазируем только bug10 (то есть все коммиты после 2.0
тега до HEAD
из bug10
ответвления) :
PS D:\git\tests\rebaseRepo> git co bug10
PS D:\git\tests\rebaseRepo> git rebase --onto legacy 2.0
First, rewinding head to replay your work on top of it...
Applying: a first bug10 fix
Applying: a second bug10 fix
В этот момент bug10
было воспроизведено поверх legacy
без всех других промежуточных коммитов .
Теперь мы можем перемотать HEAD
из legacy
к вершине воспроизводимой ветви bug10
.
PS D:\git\tests\rebaseRepo> git co legacy
Switched to branch 'legacy'
PS D:\git\tests\rebaseRepo> git merge bug10
Updating dbcc7aa..cf02bfc
Fast forward
toBeFixedFile.txt | Bin 38 -> 104 bytes
1 files changed, 0 insertions(+), 0 deletions(-)
Содержание соответствует тому, что нам нужно:
- У нас есть все устаревшее содержимое:
PS D:\git\tests\rebaseRepo> type legacy.txt
legacyContent
aFirstLegacyEvol
- содержимое для ветви
main
доступно только до тега 1.0
(корень для ветви legacy
), и больше нет .
PS D:\git\tests\rebaseRepo> type mainFile.txt
mainFile
firstMainEvol
- и исправления
bug10
здесь:
PS D:\git\tests\rebaseRepo> type toBeFixedFile.txt
contentToBeFixed
aFirstBug10Fix
aSecondBug10Fix
Вот и все.
Идея состоит в том, чтобы вытянуть эту «улучшенную» ветвь legacy
в исходном репо, которая по-прежнему будет иметь bug10
неизменной (т.е. все еще начиная с тега 2.0
, и не воспроизводиться нигде, как мы это делали на * 1167). *.
В этом клонированном репо я отслеживаю ветку origin/legacy
, чтобы объединить в нее ветку legacy
другого удаленного источника: rebaseRepo
.
PS D:\git\tests\rebaseRepo> cd ..
PS D:\git\tests> git clone mainRepo finalRepo
PS D:\git\tests> cd finalRepo
PS D:\git\tests\finalRepo> git co -b legacy origin/legacy
В этом оригинальном репо (я только клонировал его, чтобы не связываться с состоянием mainRepo, на случай, если у меня были какие-то другие эксперименты), я объявлю rebaseRepo
удаленным и получу его ветви.
PS D:\git\tests\finalRepo> git remote add rebasedRepo D:/git/tests/rebaseRepo
PS D:\git\tests\finalRepo> type D:\git\tests\finalRepo\.git\config
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
url = D:/git/tests/mainRepo
[branch "master"]
remote = origin
merge = refs/heads/master
[branch "legacy"]
remote = origin
merge = refs/heads/legacy
[remote "rebasedRepo"]
url = D:/git/tests/rebaseRepo
fetch = +refs/heads/*:refs/remotes/rebasedRepo/*
PS D:\git\tests\finalRepo> git fetch rebasedRepo
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 6 (delta 3), reused 0 (delta 0)
Unpacking objects: 100% (6/6), done.
From D:/git/tests/rebaseRepo
* [new branch] bug10 -> rebasedRepo/bug10
* [new branch] legacy -> rebasedRepo/legacy
* [new branch] master -> rebasedRepo/master
Теперь мы можем обновить legacy
, не касаясь bug10
:
PS D:\git\tests\finalRepo> git merge rebasedRepo/legacy
Updating dbcc7aa..4919b68
Fast forward
toBeFixedFile.txt | Bin 38 -> 104 bytes
1 files changed, 0 insertions(+), 0 deletions(-)
Вы можете повторять процесс столько раз, сколько захотите, всякий раз, когда новые коммиты bug10
необходимо воспроизвести поверх старой ветки legacy
, не включая все промежуточные коммиты.