2010-03-03 2 views
286

Ситуация:Как переместить определенные коммиты в другую ветку в git?

  • владелец находится в X;
  • quickfix1 находится в X + 2 совершает

Тогда я начал работать над quickfix2, но случайно принял quickfix1 в качестве исходной ветви для копирования, а не мастер. Теперь quickfix2 находится в X + 2, совершает + 2 соответствующих фиксации.

Теперь я хочу иметь ветку с quickfix2, но без двух коммитов, принадлежащих quickfix1.

Я попытался создать патч из определенной версии в quickfix2, но патч не сохраняет историю фиксации. Есть ли способ сохранить мою историю фиксации, но есть ветвь без изменений в quickfix1?

+0

Возможный дубликат [Переместить последние фиксации в новую ветку с помощью Git] (http://stackoverflow.com/questions/1628563/move-the-most-recent- commits-to-a-new-branch-with-git) – Kevin

+4

@Kevin Этот вопрос задает только вопрос о переходе от одного ветви на другую, у этого есть дополнительное требование * not *, включая коммиты на 'quickfix1'. (Обратите внимание на разницу в ответах.) –

+0

@ScottWeldon Хорошая точка, спасибо. – Kevin

ответ

274

Это классический случай rebase --onto:

# let's go to current master (X, where quickfix2 should begin) 
git checkout master 

# replay every commit *after* quickfix1 up to quickfix2 HEAD. 
git rebase --onto master quickfix1 quickfix2 

Таким образом, вы должны перейти от

o-o-X (master HEAD) 
    \ 
     q1a--q1b (quickfix1 HEAD) 
       \ 
       q2a--q2b (quickfix2 HEAD) 

к:

 q2a'--q2b' (new quickfix2 HEAD) 
    /
o-o-X (master HEAD) 
    \ 
     q1a--q1b (quickfix1 HEAD) 

Лучше всего это делать на чистой работы дерево.
See git config --global rebase.autostash true, особенно after Git 2.10.

+19

Помните, что эти шаги изменят историю quickfix2, поэтому, если вы уже поделились веткой, вместо этого используйте вишневый сбор (см. Следующие ответы). –

+0

Только для записей: с записью SmartGit просто перетащите 'q2a' на' X' и выберите * Rebase 2 commits * из параметров встречающегося диалога. –

+1

@ThomasS. Интересно.Это хорошая реализация GUI 'git rebase -onto'. – VonC

117

Вы можете использовать git cherry-pick, чтобы просто выбрать фиксацию, которую хотите скопировать.

Возможно, лучший способ - создать ветвь из мастера, затем в этой ветке используйте git cherry-pick на 2 коммитах из quickfix2, которые вы хотите.

20

Я считаю, что это:

git checkout master 
git checkout -b good_quickfix2 
git cherry-pick quickfix2^ 
git cherry-pick quickfix2 
+2

'cherry-pick' работает с хэшами фиксации, поэтому, если вы просто хотите захватить коммит где-нибудь и поместить его в другое место, это путь. Просто убедитесь, что вы сначала выполнили 'checkout ' правильной ветви. –

95

Самое простое, что вы можете сделать, это вишня сбор диапазон. Он делает то же самое, как rebase --onto, но легче для глаз :)

git cherry-pick quickfix1..quickfix2 
+5

также не теряет оригинальные коммиты, IIUC, поэтому кажется предпочтительным для «play-it-safes», как я;) или «rebase -onto» также сохраняет исходные изменения? – akavel

+6

«rebase» и «cherry-pick» дают вам новые ключи SHA. Это потому, что каждая фиксация является ** уникальным ** моментальным снимком репозитория. – Christoph

+4

Что означало @akavel, так это то, что вишневый киндер сохранит оригинальные коммиты в своей ветке, что верно –

-1

Единственный работающий способ, который я нашел:

git show>~/some_file.txt 
git checkout master 
git checkout -b new_branch 
git apply -stat ~/some_file.txt 
git apply -check ~/some_file.txt 
git apply ~/some_file.txt 

Затем вам нужно зафиксировать изменения еще раз, но это гораздо проще затем сделайте это вручную ...