Во время выполнения git merge – можно указать опцию --no-ff, что бы гит сохранил историю коммитов в feature-бранче (или девелоп-бранче, кому как удобнее называть).
Рассмотрим пример.
Создаём каталог:
mkdir testrepo
Создаём в нём репозиторий:
cd testrepo/ && git init .
Initialized empty Git repository in /home/setevoy/Temp/testrepo/.git/
Создаём и добавляем тестовый файл:
touch testfile
git add testfile
git commit -m "testfile added to master"
[master (root-commit) 6bb0bd5] testfile added to master
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 testfile
Проверяем:
git log --pretty=oneline --abbrev-commit
6bb0bd5 (HEAD -> master) testfile added to master=
Создаём новый тестовый бранч testbranch:
git checkout -b testbranch
Switched to a new branch 'testbranch'
Вносим изменения в файл:
echo testchanges > testfile
Коммитим их:
git add testfile
git commit -m "testchanges"
[testbranch 1901bcb] testchanges
1 file changed, 1 insertion(+)
Проверяем:
git log --pretty=oneline --abbrev-commit
1901bcb (HEAD -> testbranch) testchanges
6bb0bd5 (master) testfile added to master
Переключаемся на master:
git checkout master
Switched to branch 'master'
Мерджим без --no-ff:
git merge testbranch
Updating 6bb0bd5..1901bcb
Fast-forward
testfile | 1 +
1 file changed, 1 insertion(+)
Вот оно – Fast-forward.
Проверяем историю:
git log --pretty=oneline --abbrev-commit
1901bcb (HEAD -> master, testbranch) testchanges
6bb0bd5 testfile added to master
Т.е. HEAD будет перенесён напрямую с master на master, и вся история коммитов будет иметь линейный вид, как будто все изменения выполнялись в одном бранче.
Но: git применит fast forward только в том случае, если в master за время работы над testbranch не было изменений.
Переключаемся на testbranch:
git checkout testbranch
Switched to branch 'testbranch'
Вносим изменения:
echo "testchanges from testbrahc" >> testfile
Коммитим изменения:
git add testfile
git commit -m "new testchanges from testbrach"
[testbranch 1ee6e60] new testchanges from testbrach
1 file changed, 1 insertion(+)
Переключаемся на мастер:
git checkout master
Switched to branch 'master'
Вносим изменеия тут:
git commit -m "new testchanges from master"
On branch master
nothing to commit, working tree clean
Коммитим их:
git add testfile
git commit -m "new testchanges from master"
On branch master
nothing to commit, working tree clean
Мерджим testbranch в master без --no-ff:
git merge -m "testbrahc merge to master" testbranch
Merge made by the 'recursive' strategy.
testfile | 1 +
1 file changed, 1 insertion(+)
Merge made by the ‘recursive’ strategy.
Проверяем дерево:
!671
git log --graph --oneline --all
* 5318384 (HEAD -> master) testbrahc merge to master
|\
| * 1ee6e60 (testbranch) new testchanges from testbrach
* | 2c4bab0 Merge branch 'testbranch'
|\ \
| |/
| * 93e7773 new testchanges
|/
* 1901bcb testchanges
* 6bb0bd5 testfile added to master
Теперь изменения бранча testbranch идут в отдельной ветке даже без указания no fast-forward.
Т.е., основная идея в использовании fast forward git-ом – это “не плодить лишних сущностей”, если в этом нет необходимости (верный последователь принципа Бритвы Оккама): если в мастер не было изменений, то при мердже из девелопа все коммиты будут в ветке мастера.
Если же изменения были в мастере, и в девелоп-ветке – то git сохранит две отдельных линии коммитов.