Разница между git rebase и git reset - PullRequest
0 голосов
/ 11 сентября 2018

Скажите, у меня есть это:

A - B - C - E - F    [integration]
 \
  G - H - I          [feature]

после коммита I мы перебазируем с интеграцией:

git fetch origin
git rebase integration

так что теперь у нас есть:

A - B - C - E - F    [integration]
 \
  B - C - E - F - G - H - I          [feature]

и затем скажем, что мы объединяем ветвь функции с интеграцией, тогда мы имеем:

A - B - C - E - F - G - H - I   [integration]
 \
  B - C - E - F - G - H - I          [feature]

(я думаю, что это правильно), но я не понимаю, чем это отличается от того, чтобы вообще не опровергать?

Ответы [ 2 ]

0 голосов
/ 12 сентября 2018

Ваш чертеж вводит вас в заблуждение.

Запомните следующее:

  • "Истинное имя" коммита - это его идентификатор хеша.
  • Каждый коммит хранит хэшИдентификатор его родительского коммита или для коммита слияния всех его родителей.
  • Никакой коммит нельзя изменить вообще, но коммиты можно скопировать в новые замены.

Если это помогает, думайте о коммитах как о больших, прочных вещах: например, кирпичах и балках, составляющих здание.(Как и кирпичи Lego негабаритного размера, каждый кирпич имеет некоторый соединитель (и) с каким-то другим кирпичом, и мы соединяем наши кирпичи вместе для создания цепочек. Эти соединения проходят через хэш-идентификаторы: они выходят из дочернего коммита и указывают на родительский.)

Ветвь Имена , с другой стороны, являются очень легкими предметами.Они как липкие заметки, которые вы надеваете на коммит, затем снимаете с себя и затем надеваете на другой коммит.

Так что, если у вас есть это:

A <-B <-C <-E <-F   <-- integration
 \
  G <-H <-I   <-- feature

, вы не можете получить свой второйизображение, потому что существующий коммит G записывает A хэш-идентификатор.Вы не можете иметь G, у которого F в качестве родителя.Вы также не должны не рисовать коммит дважды, если это вообще возможно: коммиты уникальны, есть только один коммит G.

git cherry-pick является строительным блоком для копирование коммитов

Часто мы попадаем в ситуацию, в которой у нас есть коммит, например G, который в порядке, но нам бы хотелось, чтобы он был больше, если бы он был немного другим.Нам нужна новая копия, которая похожа на G, но имеет F в качестве родителя и имеет снимок дерева исходного кода, отличный от исходного G.Давайте назовем новый коммит G', чтобы отличить его от G, но напомним, что он очень много , как G.Мы хотим, чтобы разница между F и G' была такой же, как разница между A и G, таким образом учитывая любые изменения, необходимые из-за коммитов B-C-E-F тоже.Итак, нам нужен граф коммитов, который выглядит следующим образом:

              G'  <-- new-and-improved-feature
             /
A--B--C--E--F   <-- integration
 \
  G--H--I   <-- feature

Если мы затем скопируем коммит H в новый и улучшенный H' и скопируем Iк новым и улучшенным I' мы получаем это:

              G'-H'-I'  <-- new-and-improved-feature
             /
A--B--C--E--F   <-- integration
 \
  G--H--I   <-- feature

git reset перемещает метки

Что делает git reset - ну, один из несколькихвсе, что он может сделать, но это то, что мы делаем с ним сейчас, - это переместить липкие метки с названиями ветвей.

Есть одна липкая метка, на которой мы написали слово feature.Эта наклейка прикреплена для фиксации I прямо сейчас.Но мы только что использовали git cherry-pick три раза, чтобы скопировать последовательность G-H-I в последовательность G'-H'-I', в нашей новой и улучшенной установке.

Если у нас теперь есть Git, то очиститепометить feature off commit I и вместо этого вставить его в commit I', мы получим следующее:

              G'-H'-I'  <-- feature (HEAD), new-and-improved-feature
             /
A--B--C--E--F   <-- integration
 \
  G--H--I   <-- ORIG_HEAD

Чтобы это произошло, мы запускаем: git checkout feature; git reset new-and-improved-feature.

Команда git reset устанавливает это специальное имя ORIG_HEAD, чтобы помнить, куда feature имел обыкновение идти.Теперь метка feature прикреплена к коммиту I', но есть способы найти I, включая этот трюк ORIG_HEAD.

(нам больше не нужна метка «новая и улучшенная функция»)поэтому мы можем удалить его сейчас.)

Обратите внимание, что фиксация не изменилась .Оригинал G все еще находится в хранилище.Запустив git log ORIG_HEAD, мы все еще можем увидеть его, по крайней мере, пока не выполним другую команду Git, которая использует ORIG_HEAD для запоминания какого-либо другого коммита.Мы увидим I, затем H, затем G.Мы также можем использовать reflog для feature, чтобы найти идентификатор хеша для коммитов G, H и I.Пока у нас есть хэш-идентификатор или имя для хэш-идентификатора, мы можем найти коммит.(Срок действия этих записей reflog истекает - у них есть отметка даты, и через месяц или три Git удаляет запись reflog.)

Если мы используем имя feature, мы найдем новые копии вместо оригинальных коммитов. Из-за этого кажется, что коммиты изменились, пока мы не уделяем пристального внимания и не замечаем, что на самом деле это new коммиты.

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

git rebase = вишня плюс сброс

Это подводит нас к выводу: git rebase по существу git cherry-pick некоторого набора коммитов , за которым следует git reset. То есть мы начинаем с копирования коммитов в новые и - мы надеемся - улучшенные версии; затем мы используем git reset, чтобы попытаться заставить всех использовать улучшенные коммиты вместо оригиналов.

Любой, у кого еще есть оригиналы, не будет одурачен! Если кто-то еще - какой-то другой репозиторий Git - все еще имеет оригинальные коммиты, мы должны убедить них перейти на новый улучшенные коммиты тоже. Но если мы единственные, кто имеет доступ к коммитам, нам нужно только обмануть себя, что, вероятно, проще.

0 голосов
/ 11 сентября 2018

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

Я нашел отличное объяснение разницы между двумя при переполнении стека: здесь

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

...