Как сделать так, чтобы определенные коммиты основывались на другой ветке в git?

Ситуация:

  • мастер находится в X
  • quickfix1 находится на X + 2 коммитов

Такой, что:

o-o-X (master HEAD)
     \
      q1a--q1b (quickfix1 HEAD)

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

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

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

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

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


person Alex Yarmula    schedule 03.03.2010    source источник
comment
Возможный дубликат Переместить самые последние фиксации ) в новую ветку с Git   -  person Kevin    schedule 28.12.2016
comment
@Kevin В этом вопросе спрашивается только о перемещении коммитов из одной ветки в другую, здесь есть дополнительное требование: не включая коммиты на quickfix1. (Обратите также внимание на разницу в ответах.)   -  person Scott Weldon    schedule 29.12.2016


Ответы (5)


Это классический случай _ 1_:

 # 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)

to:

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

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

person VonC    schedule 03.03.2010
comment
Помните, что эти шаги изменят историю quickfix2, поэтому, если вы уже поделились веткой, вместо этого используйте выбор вишни (см. Следующие ответы). - person Max Chernyak; 10.01.2013
comment
Только для записей: с журналом SmartGit просто перетащите q2a на X и выберите Rebase 2 commits из параметров появившегося диалогового окна. - person Thomas S.; 27.07.2015
comment
@ThomasS. Интересный. Это хорошая реализация git rebase --onto. - person VonC; 27.07.2015
comment
Я должен признать, что делаю глупые вещи, например, совершаю фиксацию на неправильной ветке чаще, чем должен, графический интерфейс просмотра журнала SmartGit столько раз спасал меня от одной и той же ситуации. - person WORMSS; 06.08.2015
comment
@WORMSS - еще один интересный графический интерфейс: kickstarter.com/projects/diffplug/git-for- diffplug - person VonC; 06.08.2015
comment
Осторожный! Если вы не будете осторожны, ваш рабочий каталог будет перезаписан. Я потерял работу с этой командой. - person Cosine; 29.05.2017
comment
@Cosine Согласен. Я отредактировал свой ответ, добавив ссылку на конфигурацию rebase.autostash: это позволит избежать потери незавершенной работы в рабочем дереве при выполнении перебазирования. - person VonC; 29.05.2017

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

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

person DJ.    schedule 03.03.2010
comment
Это также лучший вариант, если вы хотите переместить только одну фиксацию. Спасибо. - person Alex from Jitbit; 17.01.2020

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

git cherry-pick quickfix1..quickfix2
person Christoph    schedule 15.08.2012
comment
кроме того, он не теряет исходные коммиты, IIUC, поэтому кажется предпочтительным для таких программ, как я;) или rebase --onto также сохраняет исходные изменения? - person akavel; 12.07.2013
comment
и rebase, и cherry-pick дают вам новые ключи SHA. Это потому, что каждая фиксация - это уникальный снимок репозитория. - person Christoph; 18.09.2013
comment
Что имел в виду @akavel, так это то, что cherry-pick сохранит исходные коммиты в своей ветке, что верно - person Mr_and_Mrs_D; 31.03.2014
comment
Как бы то ни было, я попытался cherry-pick диапазон, как в этом ответе, и это запутало мое репо. Мне приходилось делать отдельные cherry-picks для каждой фиксации. (И, возможно, это само собой разумеется, но в случае, если кто-то борется, вы должны cherry-pick в хронологическом порядке, в котором были применены ваши коммиты.) - person carmenism; 06.09.2016
comment
git checkout здесь имеет решающее значение. какая у тебя ГОЛОВА :)? - person Sławomir Lenart; 22.12.2016

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

git checkout master
git checkout -b good_quickfix2
git cherry-pick quickfix2^
git cherry-pick quickfix2
person Matthew Flaschen    schedule 03.03.2010
comment
cherry-pick работает с хешами коммитов, поэтому, если вы просто хотите взять коммит откуда-то и поместить его в другое место, это лучший вариант. Просто убедитесь, что вы сначала выполнили checkout <branch> правильную ветку. - person John Leidegren; 16.02.2016

// on your branch that holds the commit you want to pass
$ git log
// copy the commit hash found
$ git checkout [branch that will copy the commit]
$ git reset --hard [hash of the commit you want to copy from the other branch]
// remove the [brackets]

Другие более полезные команды с пояснениями: Git Guide

person Gopher    schedule 25.09.2019