Можно ли задним числом превратить набор коммитов в ветку?

Скажем, у меня есть git-репозиторий, и я работаю над мастером, могу ли я задним числом создать ветку. Например:

A - B - C - A1 - D - A2 - E

Я хочу, чтобы это выглядело так:

A - A1 - A2   
\           \   
B - C - D - E

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

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

13.12.2008 06:31:03
5 ОТВЕТОВ
РЕШЕНИЕ

Конечно вы можете. (С Git все равно мало что нельзя сделать :)

git checkout -b new-branch hash-of-A
git cherry-pick hash-of-A1
git cherry-pick hash-of-A2

Это создаст новую ветку, начиная с коммита A. После этого вы снова возвращаетесь к тому же коммиту, создавая другую ветку:

git checkout -b new-branch2 hash-of-A
git cherry-pick hash-of-B
git cherry-pick hash-of-C
git cherry-pick hash-of-D
git cherry-pick hash-of-E
git merge new-branch

Теперь вам просто нужно объединить new-branchи new-branch2получить желаемую структуру и отбросить старую ветку.

Конечно, то, что сказал Дастин, остается в силе: хеши коммитов изменятся, поэтому делать это следует только в том случае, если вы еще не опубликовали свои изменения.

22
13.12.2008 12:55:14
Итак, если ветвь, на которой я работал, была master, я должен переместить имя master в голову new-branch2? Имеет смысл. Спасибо.
Otto 14.12.2008 03:42:22
Да, с тех пор мои навыки интерактивного ребазинга значительно улучшились. :)
Bombe 21.01.2011 11:19:19

Вы не можете сделать это прозрачно, потому что хэши должны будут измениться, но вам просто нужно разветвлять HEAD и перебазировать -i обе ветви, чтобы отбросить соответствующие изменения.

6
13.12.2008 08:26:21

Что вы хотите сделать, это на самом деле переписать историю. Идентификаторы коммитов будут меняться, а в некоторых случаях будет меняться набор изменений, заданный коммитами. Так что, если есть шанс, что кто-то может основывать работу на старой версии ветки, которую вы хотите изменить, лучше этого не делать. Но если вы не опубликовали эту ветку, не стесняйтесь.

Давайте предположим, что ветвь, которую мы хотим изменить, называется «master», а точка, в которой мы хотим начать новую ветку, называется «A» (в данном примере одно из имен, которые вы можете использовать, - «master ~ 6»).

Во-первых, давайте создадим новую ветку из коммита 'A', назовем его 'fixes'

$ git checkout -b fixes A

Это также сделало бы ветки 'исправлениями' текущими. Поскольку есть только несколько коммитов, которые мы хотим отменить выбор вишни, мы можем выбрать их с помощью исправлений ветви:

$ git cherry-pick A1
$ git cherry-pick A2

Затем мы хотим удалить коммиты 'A1' и 'A2' из ветви 'master'. Поскольку мы хотим удалить только несколько коммитов и, возможно, многие другие, которые мы хотим сохранить, мы можем использовать для этого «git rebase --interactive»:

$ git rebase -i fixes master

Редактор будет запущен со всеми коммитами в 'master' после коммита 'A' (который является общим коммитом, т.е. базой слияния ветки 'master' и ветки 'fixes'). Список будет выглядеть так:

pick deadbee B
pick fa1afe1 C
pick a98d4ba A1
...

Удалите строки с коммитами «А1» и «А2», сохраните изменения, закройте редактор (или отправьте изменения в инетрактивную перебазировку), и git повторно применяет все коммиты, кроме тех, которые вы удалили.

Тогда вы можете завершить с

$ git merge fixes

(git-rebase оставил нас на переписанной ветке 'master').

1
15.12.2008 00:52:48

Если вы хотите, чтобы все коммиты после ревизии XXX происходили в ветке, я нахожу это намного проще, чем другие предложенные методы.

$ git branch fixes       # copies master to new branch
$ git reset --hard XXX   # resets master to XXX

Это описано на странице справки git в resetразделе «Отменить коммит, сделав его веткой темы».

105
20.01.2011 18:11:17
Рад, что прочитал до последнего ответа! - это, безусловно, самое простое решение (по крайней мере, для моего конкретного случая использования)
Brian Leathem 20.02.2012 22:25:02
Я вернулся к этому ответу во второй раз на этой неделе. Я хотел бы дать @alltom еще один голос!
Brian Leathem 24.02.2012 22:07:26
Полезное значение для этого XXX просто origin/master: при условии, что вы были на masterветке, возьмите все неоттолкнутые коммиты и вместо этого рассматривайте их как ветвь. Вы также, вероятно, захотите git checkout fixesв конце фактически вернуться к своей новой ветке.
Jesse Glick 19.08.2014 17:49:34
Сценарий @ JesseGlick является полезным частным случаем, о котором стоит знать.
Roly 14.05.2015 07:27:53

Забудь обо всем, что собирает вишню. Просто перебазируйте -i дважды, пропуская изменения, каждый раз создавая новую ветвь и затем объединяя 2.

0
20.01.2011 20:20:32