Как я могу переместить фиксацию из туловища в ветвь в Git?
Я сделал кучу коммитов хозяину и понял после того, что они должны были быть в ветке.
Я рассмотрел различные вещи, касающиеся перезагрузки и слияния и сброса мастера. Но никакие попытки манипуляции не привели к истории, которая выглядит так, как я пытаюсь сделать.
Мои попытки заставили меня поверить, что для перемещения мастера назад во времени требуется некоторая комбинация rebase --onto
и reset --hard
. Но мое понимание ветвления Git оставляет желать лучшего. Часть этого заключается в том, чтобы узнать, как я могу его использовать.
Следует отметить, что ни одно из изменений, которые я пытаюсь переместить, было вытолкнуто.
Current
* remote/trunk
--o--a--b--c--d--e--f <- master
|
o <- remote branch foo
Желаемый результат
* remote/trunk
--o <- master
|
o--a--b--c--d--e--f <- remote branch foo
Ответы
Ответ 1
Я не уверен, что переименование ветвей - правильное решение, так как оно доставит вас от:
* remote/trunk
--M--a--b--c--d--e--f <- master
|
F <- remote branch foo
в
--F <- master
|
M--a--b--c--d--e--f <- remote branch foo
* remote/trunk
(если вы переименовали remote/foo
, что не рекомендуется: сначала вы должны отследить его, а затем переименовать, но даже если конечный результат отличается от того, что вам нужно)
который не является желаемым результатом (foo нужно начинать с F, а не M):
* remote/trunk
--M <- master
|
F--a--b--c--d--e--f <- remote branch foo
Вы можете достичь этого только с помощью rebase --onto
git checkout --track -b origin/foo # create a local branch named after the remote one
git branch tmp # mark current foo HEAD to 'F'
git branch -f foo master # put foo where it should b: at 'f'
git branch -f master tmp^ # reset master to M, parent of tmp
git checkout tmp # go to where we must replay the commits
git rebase --onto tmp master foo # replay a to f on top of tmp
git svn dcommit # push the local foo in order to update remote/foo
дает вам:
* remote/trunk
--M <- master
|
F--a'--b'--c'--d'--e'--f' <- local foo and remote branch foo
Ответ 2
Вариант ответа Мартина, который не обязательно будет применим к вашей ситуации, но я все равно хочу его опубликовать:)
Предположим, что вы забыли создать ветвь в commit o
, поэтому у вас есть:
x--y--z--o--a--b--c--d--e--f master
|
+
[forgot to make a branch here]
И тогда вы поняли, что вы действительно хотели:
x--y--z--o master
|
+--a--b--c--d--e--f topic
Что вы можете сделать в этом случае - создать ветку в o
с помощью хеша:
git branch topic # creates new branch 'topic' - will be at commit `f`
git checkout o -b newmaster # creates new branch called newmaster pointing on commit `o` (please replace `o` with the actual hash)
git branch -M newmaster master # force rename newmaster to master (means master points on hash `o`)
Вы будете в главной ветке (commit o
), так что вы можете сделать последний шаг:
git checkout topic
Конечно, хэш может быть только первыми 5 символами.
ИЗМЕНИТЬ
Не важно, что вы используете git-svn
, что действительно важно, так это то, что вы не опубликовали свою главную ветвь в любой момент после o
Ветвь в git - это не что иное, как указатель на фиксацию. Вот почему ветвление настолько дешево: вы просто создаете указатель, и у вас есть ветка.
Я не знаю, как отслеживать удаленные ветки, хотя вам может потребоваться установить это после переименования/перемещения ваших ветвей.
Ответ 3
Почти правильно то, что hasen j предлагает, но мне пришлось сделать несколько небольших изменений (и я использую git -svn):
# create the branch with your commits
git branch performance
# fork the master to a new branch at the commit before your local, non pushed commits
git branch newmaster 2d0516dfe8252de87
# checkout your branch
git checkout performance
# rename the newmaster
git branch -M newmaster master
# now checkout the master
git checkout master
Вы не можете переименовать ветку, на которой вы находитесь, поэтому я проверил ветвь производительности, в которой я переместил свои коммиты.