GIT: манипуляция коммитами
git merge
git merge COMMIT
— команда, которая ищет общего предка у ГОЛОВЫ и COMMIT и переводит ГОЛОВУ в состояние репозитория, в котором есть изменения как из головного коммита, так и из COMMIT, то есть осуществляет слияние двух наборов изменений. См git-merge(1)
, там картинка.
Если COMMIT является потомком головного, то для слияния не нужно никаких изысков: сам COMMIT является результатом слияния, достаточно переписать ГОЛОВУ на коммит. См. раздел FAST-FORWARD MERGE
.
Если же COMMIT не является потомком ГОЛОВЫ, происходит true merge.
True merge
См. раздел TRUE MERGE
из git-merge(1)
и разделы ниже.
True merge создаёт коммит (merge commit), у которого два родительских: COMMIT и головной. Этот коммит представляет состояние репозитория, в котором есть изменения и из COMMIT, и из головного.
Иногда изменения конфликтуют и сделать merge commit автоматически не получается, и пользователь должен руками разрешить конфликты. В таком случае создаётся указатель MERGE_HEAD
, который как HEAD
, но указывает на COMMIT. Файлы, в которых возникли конфликты, записываются в нескольких копиях в index с особыми stage number-ами (1 — общий предок, 2 — HEAD
, 3 — MERGE_HEAD
), а в рабочем дереве лежат смешанные вариации на тему.
git merge --continue
создаёт merge commit после того, как в index добавлены файлы с 0 как stage number.
git rebase
git rebase
— команда, осуществляющая смену родительского коммита для набора изменений. См. git-rebase(1)
, там картинка.
Пусть головной коммит — и вызвана команда git rebase
. Команда найдёт ближайшего общего предка у и — пусть это . Затем команда будет проходиться по пути от к и пытаться последовательно merge-ить изменения в каждом из коммитов по пути к . Так выстроится новая цепочка, идентичная цепочке от к , но начинающаяся с .
Можно достраивать цепочку не к , а к произвольному , используя флаг --onto
.
git rebase -i
См. INTERACTIVE MODE
страницы git-rebase(i)
.
git rebase -i
(--interactive
) позволяет не просто перенести цепочку от к на , но и модифицировать эту цепочку на лету.
Откроется текстовый редактор, где можно выбрать, что делать с каждым коммитом в цепочке: отредактировать, изменить commit-сообщение, сделать его изменения частью идущего перед ним коммита, вообще пропустить…
git rebase -i
кроет великую мощь, не пренебрегайте ей.
git cherry-pick
git cherry-pick
— команда, которая применяет наборы изменений из перечисленных коммитов к ГОЛОВЕ.
Например, git cherry-pick КОММИТ1 КОММИТ2
создаст два новых коммита:
КОММИТ1'
, аналог применения изменений изКОММИТ1
- к ГОЛОВЕ, и
КОММИТ2'
, аналог применения изменений изКОММИТ2
к КОММИТ1’. ГОЛОВА станетКОММИТ2
.
git reflog
git reflog
не создаёт изменения, а спасает от уже сделанных. reflog хранит сведения о том, на что указывали HEAD
и ветки в последнее время. Со временем эта информация
удаляется1.
В случае, например, неудачного git rebase
относительно можно посмотреть в git reflog
, какой коммит недавно был головным. Один из них будет указывать на .
Куда деваются ненужные вещи?
Пусть мы сделали git rebase
из . Это создало коммит с предком . Если мы верим в это действие, нам больше не нужен.
Когда и как ненужны вещи исчезают?
git-gc(1)
— команда, которая время от времени исполняется сама по себе и удаляет ненужные объекты. Ненужные — те, которые не упоминаются вreflog
, до которых нельзя дойти по родительским ссылкам от веток, тегов,HEAD
иindex
.