Как объяснить "git pull --rebase" простыми словами?
Я думаю, что понял git pull
и вот как я это объясняю, что я называю "простыми терминами":
- Вообще говоря,
git pull
о слиянии "удаленной" ветви с "локальной" веткой. - Более подробно, git использует содержимое "удаленной" ветви для "обновления" / "изменения" содержимого "локальной" ветви.
- Более подробно, если файл был изменен в "локальной" ветви, но не в "удаленной" ветви, то после слияния содержимое файла будет таким же, как содержимое в "локальной" ветви. Обратное тоже верно. Если файл был изменен в "удаленной" ветви, но не в "локальной" ветви, содержимое будет извлечено из "удаленной" ветви.
- Если файл был изменен в обеих ветвях ("локальных" и "удаленных"), то git попытается получить изменения из обеих веток. Если изменения происходят в разных местах файла, оба изменения будут применены и будут присутствовать в содержимом файла после слияния.
- Если изменения происходят в одном и том же месте, мы имеем то, что известно как "конфликт слияния", и я не буду касаться этого случая для простоты.
- В результате слияния мы модифицируем "локальный" репозиторий и, следовательно, нам необходимо "зафиксировать".
Теперь я хочу получить такое же объяснение git pull --rebase
, Я не хочу использовать такие термины, как "голова", "индекс", "выборка", "восходящий поток", потому что эти термины / концепция только сбивают с толку начинающих, таких как я. Я знаю, что мне нужно изучить эти "продвинутые" концепции, и я делаю это, читая учебники, но сейчас, как часть моего учебного процесса, я хочу понять, git pull --rebase
,
ADDED
Я думаю, что в какой-то момент я услышал следующее объяснение. От git pull --rebase
, Когда мы объединяем, мы делаем это не "симметрично", как описано выше. Вместо этого мы сначала "забываем" об изменениях в "локальном" хранилище и применяем только изменения из "удаленного" хранилища. Делая это, мы в основном "копируем" удаленный репозиторий как есть. После этого мы применяем изменения из "локального" хранилища сверху. Однако мне все еще не ясно, что именно это означает. В частности, что означает "сверху".
2 ответа
Я вижу две вещи, которые можно уточнить: вы сосредотачиваетесь на состоянии файла в двух ветвях, но лучший способ рассмотреть происходящее с точки зрения произошедших изменений. Вторая проблема заключается в том, что git pull
является сокращением для двух операций: git fetch
, а также git merge
, Да, ты пишешь, что "не хочешь использовать такие слова, как fetch
", но это не" продвинутая концепция ". Если вы хотите понять, что происходит, вам нужно начать с этого.
git fetch
по сути, сообщает местному репо об изменениях, о которых он не знал.git merge
объединяет вновь прибывшие изменения с вашими локальными изменениями.
Подвох в том, что если что-то происходило в обоих репозиториях без синхронизации, они могли расходиться:
... b--o--o--o--o (remote)
\
x--x--x (local)
Выше показано время слева направо; самая правая точка - самая последняя. Таким образом, вновь поступившие изменения являются модификациями более старого состояния файлов, помеченного буквой "b".
git pull
т.е. простойgit merge
, объединит самое последнее состояние двух веток как можно лучше.git pull --rebase
будет делать вид, что ваши изменения были сделаны не в состоянии с пометкой "b", а в самом текущем удаленном состоянии. Другими словами, он попытается переписать историю так, чтобы это выглядело так:... b--o--o--o--o (remote) \ x--x--x (local)
В этом разница. Одним из следствий этого является то, что если вы не сделаете ребазинг, история вашего репо содержит несколько состояний (к которым вы можете вернуться в будущем, если хотите), где изменения "x" были применены, а изменения "o" отсутствуют. После ребазинга такого места в репозитории нет.
Просто: пока ваша работа является локальной (то есть она не была выдвинута), git pull --rebase
будет служить для воспроизведения вашей локальной работы поверх обновленной истории.
git fetch
обновит указанную историю последними коммитами удаленного репо (origin/master
например).
Тогда ваша работа (ваши местные коммиты вашего master
ветвь) будет воспроизводиться один за другим (что и делает перебазирование) поверх этой обновленной истории.
Идея состоит в том, что когда вы хотите нажать, указанный push будет очень простым и не потребует слияния, так как ваши коммиты - это просто новые коммиты, сделанные поверх origin/master
,
Обратите внимание, что вы можете полностью скрыть эту часть, начиная с Git 2.6:
git config pull.rebase true
git config rebase.autoStash true
И даже если ребаз не идет хорошо, и вы должны прервать его, Git восстановит для вас сохраненную текущую работу, начиная с Git 2.10.