Я заметил, что два блока следующих команд git имеют различное поведение, и я не понимаю, почему.
У меня есть A
и B
ветвь, которые расходятся с однимcommit
---COMMIT--- (A)
\
--- (B)
Я хочу перебазировать B
ветку на последней A
(и иметь коммит на B
ветке)
---COMMIT--- (A)
\
--- (B)
Нет проблем, если я сделаю:
checkout B
rebase A
Но если я сделаю:
checkout B
rebase --onto B A
Это не работает вообще, ничего не происходит. Я не понимаю, почему эти два поведения отличаются.
Git-клиент Phpstorm использует второй синтаксис, и поэтому он мне кажется совершенно неработающим, поэтому я прошу эту проблему с синтаксисом.
git
git-rebase
Xmanoux
источник
источник
Ответы:
ТЛ; др
Правильный синтаксис для перебазирования
B
поверхA
использованияgit rebase --onto
в вашем случае:или перебазировать
B
поверхA
начала коммита, который является родителемB
ссылки сB^
илиB~1
.Если вы заинтересованы в разнице между
git rebase <branch>
иgit rebase --onto <branch>
читать дальше.Быстрый: git rebase
git rebase <branch>
собирается перебазировать ветку, которую вы в настоящее время извлекли, на которую ссылаетсяHEAD
, поверх последнего коммита, который доступен из,<branch>
но не изHEAD
.Это наиболее распространенный случай перебазирования и, возможно, тот, который требует меньше планирования заранее.
В этом примере
F
иG
являются коммиты, которые доступны из,branch
но не изHEAD
. Говорят , чтоgit rebase branch
возьмитеD
, то есть первый коммит после точки ветвления, и перебазируйте его (т.е. измените его родителя ) поверх последнего коммита, доступного из,branch
но не изHEAD
, то естьG
.Точное: git rebase --onto с 2 аргументами
git rebase --onto
позволяет перебазировать, начиная с определенного коммита . Это дает вам точный контроль над тем, что перебазируется и где. Это для сценариев, где вам нужно быть точным.Например, давайте представим, что нам нужно сделать ребаз
HEAD
точно поверхF
начальногоE
. Мы заинтересованы только в том, чтобы внестиF
в нашу рабочую ветку, в то же время, мы не хотим сохранять,D
потому что она содержит некоторые несовместимые изменения.В этом случае мы бы сказали
git rebase --onto F D
. Это означает:Другими словами, изменить родителя в
E
отD
кF
. Синтаксисgit rebase --onto
это тогдаgit rebase --onto <newparent> <oldparent>
.Другой сценарий, в котором это пригодится, - это когда вы хотите быстро удалить некоторые коммиты из текущей ветви без необходимости интерактивной перебазировки :
В этом примере, чтобы удалить
C
иE
из последовательности вы бы сказалиgit rebase --onto B E
, или перебазироватьHEAD
поверх того,B
где был старый родительE
.Хирург: git rebase --onto с 3 аргументами
git rebase --onto
может пойти на шаг дальше с точки зрения точности. Фактически, это позволяет вам перебазировать произвольный диапазон коммитов поверх другого.Вот пример:
В этом случае мы хотим перебазировать точный диапазон
E---H
поверхF
, игнорируя, кудаHEAD
в данный момент указывает. Мы можем сделать это, сказавgit rebase --onto F D H
, что означает:Синтаксис
git rebase --onto
с диапазоном коммитов затем становитсяgit rebase --onto <newparent> <oldparent> <until>
. Хитрость здесь помнить , что фиксация ссылается<until>
будет включен в диапазон и станет новымHEAD
после перебазироваться завершения.источник
<oldparent>
имя ломается, если две части диапазона находятся в разных ветвях. Как правило, это: «Включать каждый коммит, который доступен,<until>
но исключать каждый коммит, который доступен<oldparent>
».git rebase --onto <newparent> <oldparent>
лучшее объяснение --onto поведения, которое я видел!--onto
вариантом, но это сделало его кристально ясным! Я даже не понимаю, как я не мог понять это раньше: D Спасибо за отличный "учебник" :-)Это все, что вам нужно знать, чтобы понять
--onto
:Вы переключаете родителя в коммите, но не указываете шага коммита, только ша его текущего (старого) родителя.
источник
Короче говоря, учитывая:
Что так же, как (потому что
--onto
принимает один аргумент):Означает перебазирование коммитов в диапазоне (D, H] поверх F. Обратите внимание, что диапазон является эксклюзивным для левой руки. Он эксклюзивен, потому что проще указать 1-й коммит, набрав, например,
branch
позволитьgit
найти 1-й дивергентный коммит,branch
т. Е. КоторыйD
ведет кH
.OP чехол
Может быть изменено на одну команду:
То, что здесь выглядит как ошибка, это размещение,
B
которое означает «переместить некоторые коммиты, которые приводят к ответвлениюB
сверхуB
». Вопрос в том, что такое «некоторые коммиты». Если вы добавите-i
флаг, вы увидите, что это единственный коммит, на который указываетHEAD
. Коммит пропускается, потому что он уже применен к--onto
цели,B
и поэтому ничего не происходит.Эта команда является бессмысленной в любом случае, когда имя ветви повторяется так. Это потому, что диапазон коммитов будет некоторым коммитам, которые уже находятся в этой ветке, и во время перебазирования все они будут пропущены.
Дальнейшее объяснение и применимое использование
git rebase <upstream> <branch> --onto <newbase>
.git rebase
по умолчанию.Расширяется либо:
Автоматическая проверка после ребаз.
При использовании стандартным способом, например:
Вы не заметите, что после rebase
git
переходитbranch
к последнему перебазированному коммиту и делаетgit checkout branch
(см.git reflog
Историю). Что интересно, когда вторым аргументом является хеш коммита, а перебазирование имени ветки все еще работает, но ветка не перемещается, поэтому вы попадаете в «отсоединенную головку» вместо того, чтобы быть извлеченными в перемещенную ветвь.Пропустить первичные дивергентные коммиты.
master
В--onto
взят из 1 - гоgit rebase
аргумента.Так что на практике это может быть любой другой коммит или ветка. Таким образом, вы можете ограничить количество коммитов ребаз, взяв последние и оставив первичные дивертированные коммиты.
Будет ли перебазироваться одну фиксацию указываемого
HEAD
доmaster
и в конечном итоге в «отдельных РУКОВОДИТЕЛЯ».Избегайте явных проверок.
Значение по умолчанию
HEAD
илиcurrent_branch
аргумент контекстуально берется из того места, где вы находитесь. Именно поэтому большинство людей обращаются к ветке, которую они хотят перебазировать. Но когда 2-й аргумент rebase задан явно, вам не нужно проверять перед rebase, чтобы передать его неявным образом.Это означает, что вы можете перебазировать коммиты и ветки из любого места. Так что вместе с автоматической проверкой после ребазирования. Вам не нужно отдельно оформлять перебазированную ветку до или после перебазирования.
источник
Проще говоря,
git rebase --onto
выбирает диапазон коммитов и перебазирует их на коммит, указанный в качестве параметра.Прочитайте справочные страницы для
git rebase
, ищите "на". Примеры очень хороши:В этом случае вы говорите мерзавец перебазироваться совершающими от
topicA
кtopicB
в верхней частиmaster
.источник
Чтобы лучше понять разницу между
git rebase
иgit rebase --onto
это хорошо , чтобы знать , каковы возможные модели поведения для обеих команд.git rebase
позволяют нам перемещать наши коммиты поверх выбранной ветви. Как здесь:и результат:
git rebase --onto
более точный. Это позволяет нам выбирать конкретный коммит, где мы хотим начать, а также где мы хотим закончить. Как здесь:и результат:
Чтобы получить более подробную информацию, я рекомендую вам ознакомиться с моей собственной статьей о git rebase - onto Overview
источник
git rebase --onto F D
как set child родительского элемента D как F , не так ли?Для
onto
вас нужны две дополнительные ветки. С помощью этой команды вы можете применить коммитыbranchB
, основанныеbranchA
на другой ветке, напримерmaster
. В приведенном ниже примереbranchB
основан на,branchA
и вы хотите применить измененияbranchB
наmaster
без применения измененийbranchA
.с помощью команд:
вы получите следующую иерархию коммитов.
источник
rebase --onto branchA branchB
, это поместило бы всю главную ветвь в голову ветви A?checkout branchB: rebase --onto master branchA
?В другом случае
git rebase --onto
трудно понять: когда вы переходите на коммит, полученный в результате симметричного селектора разности (три точки '...
')Git 2.24 (Q4 2019) лучше справляется с этим делом:
См. Коммит 414d924 , коммит 4effc5b , коммит c0efb4c , коммит 2b318aa (27 августа 2019 г.) и коммит 793ac7e , коммит 359eceb (25 августа 2019 г.) от Denton Liu (
Denton-L
) .При поддержке: Эрик Саншайн (
sunshineco
) , Хунио С. Хамано (gitster
) , Эвар Арнфьорд Бьярмасон (avar
) и Йоханнес Шинделин (dscho
) .См. Коммит 6330209 , коммит c9efc21 (27 августа 2019 г.) и коммит 4336d36 (25 авг. 2019 г.). Автор Ævar Arnfjörð Bjarmason (
avar
),Помогают: Эрик Саншайн (
sunshineco
) , Хунио С. Хамано (gitster
) , Эвар Арнфьорд Бьярмасон (avar
) и Йоханнес Шинделин (dscho
) .(Слиты Junio C Hamano -
gitster
- в фиксации 640f9cd , 30 Sep 2019)На этом этапе, следующим образом: « Каковы различия между двойной точкой„
..
“и тройной точкой»...
«в Git дифференциалов совершающих диапазоны? »Здесь: «
master...
» означаетmaster...HEAD
, чтоB
: HEAD является боковым HEAD (в настоящее время проверено): вы переходите наB
.Что ты упрекаешь? Любой коммит не в master, а достижимый из
side
ветки: есть только один коммит, соответствующий этому описанию:D
... который уже поверхB
!Опять же, до Git 2.24, такое
rebase --onto
всегда приводило к тому,D
что его всегда перебазировали, несмотря ни на что.Это сродни
rebase --onto B A
ОП, который ничего не сделал.и неудачная команда была
rebase --onto C F topic
означает любой коммит послеF
, достижимыйtopic
HEAD:G
только он, а неF
сам.Ускоренная перемотка в этом случае будет включать
F
в перебазированную ветку, что неправильно.источник