Можно ли задним числом превратить набор коммитов в ветку? - PullRequest
40 голосов
/ 13 декабря 2008

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

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

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

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

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

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

Ответы [ 5 ]

100 голосов
/ 20 января 2011

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

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

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

19 голосов
/ 13 декабря 2008

Конечно можно. (В любом случае, 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, чтобы получить желаемую структуру и отбросить старую ветвь.

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

6 голосов
/ 13 декабря 2008

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

1 голос
/ 15 декабря 2008

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

Предположим, что ветвь, которую мы хотим изменить, называется «мастер», а точка, в которой мы хотим начать новую ветвь, называется «А» (в данном примере одно из имен, которые вы можете использовать, это «мастер ~ 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
...

Удалять строки с коммитами 'A1' и 'A2', сохранять изменения, закрывать редактор (или иным образом отправлять изменения в непривлекательную перебазировку) и git будет повторно применять все коммиты, кроме тех, которые вы удалили.

Затем вы можете завершить с

$ git merge fixes

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

0 голосов
/ 20 января 2011

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

...