Jaka jest różnica między `git merge ' a 'git merge --no-FF'?

Używając gitk log, nie mogłem dostrzec różnicy między tymi dwoma. Jak mogę zaobserwować różnicę (za pomocą polecenia git lub jakiegoś narzędzia)?

Author: abc, 2012-01-30

5 answers

Znacznik --no-ff uniemożliwia git merge wykonywanie "przewijania do przodu", jeśli wykryje, że bieżący HEAD jest przodkiem zatwierdzonego commita, który próbujesz scalić. Przewijanie do przodu polega na tym, że zamiast tworzyć commit scalający, git po prostu przesuwa wskaźnik gałęzi, aby wskazać nadchodzący commit. Często zdarza się to podczas wykonywania git pull bez żadnych lokalnych zmian.

Jednak od czasu do czasu chcesz zapobiec temu zachowaniu, zazwyczaj dlatego, że chcesz zachować określone topologia gałęzi (np. łączysz się w gałęzi tematycznej i chcesz mieć pewność, że tak wygląda podczas czytania historii). Aby to zrobić, możesz przekazać znacznik --no-ff i git merge będzie zawsze skonstruować merge zamiast fast-forwarding.

Podobnie, jeśli chcesz wykonać git pull lub użyć git merge w celu jawnego przewijania do przodu, a jeśli nie możesz przewijać do przodu, możesz użyć znacznika --ff-only. W ten sposób możesz regularnie robić coś takiego jak git pull --ff-only bez myślenie, a następnie, jeśli to błąd, możesz wrócić i zdecydować, czy chcesz scalić lub rebase.

 760
Author: Kevin Ballard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-30 18:51:29

Graficzna odpowiedź na to pytanie

Oto strona z jasnym wyjaśnieniem i ilustracją graficzną użycia git merge --no-FF:

różnica między git merge --no-FF i git merge

Dopóki tego nie zobaczyłem, byłem całkowicie zagubiony z Gitem. Uĺźycie --no-FF pozwala ktoĹ "przejrzeÄ ‡ historiÄ ™ jasno zobaczyÄ ‡ branĺźä™, na ktĂłrÄ ... sprawdziĺ' eĹ " do pracy. (ten link wskazuje na narzędzie wizualizacji "sieciowej" Githuba) i oto kolejna świetna Referencja z ilustracje. To odniesienie ładnie uzupełnia pierwszy z nich, skupiając się bardziej na tych, którzy są mniej zaznajomieni z Gitem.


Podstawowe informacje dla początkujących jak ja

Jeśli jesteś taki jak ja, a nie Git-guru, moja odpowiedź tutaj opisuje obsługę usuwania plików ze śledzenia Gita bez usuwania ich z lokalnego systemu plików, co wydaje się słabo udokumentowane, ale często występuje. Kolejną sytuacją newb jest uzyskanie bieżącego kodu, który wciąż udaje się umykaj mi.


Przykładowy Przepływ Pracy

Zaktualizowałem pakiet na mojej stronie internetowej i musiałem wrócić do moich notatek, aby zobaczyć mój przepływ pracy; pomyślałem, że warto dodać przykład do tej odpowiedzi.

Mój workflow poleceń git:

git checkout -b contact-form
(do your work on "contact-form")
git status
git commit -am  "updated form in contact module"
git checkout master
git merge --no-ff contact-form
git branch -d contact-form
git push origin master

Poniżej: rzeczywiste użycie, w tym wyjaśnienia.
Uwaga: poniższy wynik jest wycięty; git jest dość gadatliwy.

$ git status
# On branch master
# Changed but not updated:
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   ecc/Desktop.php
#       modified:   ecc/Mobile.php
#       deleted:    ecc/ecc-config.php
#       modified:   ecc/readme.txt
#       modified:   ecc/test.php
#       deleted:    passthru-adapter.igs
#       deleted:    shop/mickey/index.php
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       ecc/upgrade.php
#       ecc/webgility-config.php
#       ecc/webgility-config.php.bak
#       ecc/webgility-magento.php

Zauważ 3 rzeczy z góry:
1) na wyjściu widać zmiany z Aktualizacja pakietu ECC, w tym dodanie nowych plików.
2) zauważ również, że są dwa pliki (nie w folderze /ecc), które usunąłem niezależnie od tej zmiany. Zamiast mylić te usunięcia plików z ecc, zrobię później inną gałąź cleanup, aby odzwierciedlić usunięcie tych plików.
3) nie śledziłem mojego przepływu pracy! Zapomniałem o git ' IE, gdy próbowałem ponownie uruchomić ecc.

Poniżej: zamiast robić all inclusive git commit -am "updated ecc package" normalnie bym to zrobił, chciałem tylko dodać pliki w folderze /ecc. Te usunięte pliki nie były częścią mojej git add, ale ponieważ były już śledzone w git, muszę je usunąć z commita tej gałęzi:

$ git checkout -b ecc
$ git add ecc/*
$ git reset HEAD passthru-adapter.igs
$ git reset HEAD shop/mickey/index.php
Unstaged changes after reset:
M       passthru-adapter.igs
M       shop/mickey/index.php

$ git commit -m "Webgility ecc desktop connector files; integrates with Quickbooks"

$ git checkout master
D       passthru-adapter.igs
D       shop/mickey/index.php
Switched to branch 'master'
$ git merge --no-ff ecc
$ git branch -d ecc
Deleted branch ecc (was 98269a2).
$ git push origin master
Counting objects: 22, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (14/14), done.
Writing objects: 100% (14/14), 59.00 KiB, done.
Total 14 (delta 10), reused 0 (delta 0)
To [email protected]:me/mywebsite.git
   8a0d9ec..333eff5  master -> master



Skrypt do automatyzacji powyższego

Po użyciu tego procesu 10 + razy dziennie, podjąłem się pisania skryptów wsadowych, aby wykonać polecenia, więc zrobiłem prawie odpowiedni skrypt git_update.sh <branch> <"commit message"> do wykonywania powyższych kroków. Oto źródło Gist do tego scenariusz.

Zamiast git commit -am wybieram pliki z listy "zmodyfikowanych" wytworzonych przez git status i wklejam je do tego skryptu. Stało się tak, ponieważ zrobiłem dziesiątki edycji, ale chciałem zróżnicowanych nazw gałęzi, aby pomóc pogrupować zmiany.

 751
Author: Chris K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:34

Opcja --no-ff zapewnia, że fast forward merge nie nastąpi, a nowy obiekt zatwierdzania zostanie zawsze utworzony . Może to być pożądane, jeśli chcesz, aby git utrzymywał historię gałęzi funkcji.             git merge --no-FF vs git merge Na powyższym obrazku, lewa strona jest przykładem historii Gita po użyciu git merge --no-ff, A prawa strona jest przykładem użycia git merge Gdzie możliwe było połączenie ff.

EDIT : poprzednia wersja tego obrazka wskazywała tylko jednego rodzica dla commit merge. Merge commity mają wiele nadrzędnych commitów , których git używa do utrzymywania historii "feature branch" i oryginalnej gałęzi. Wiele linków nadrzędnych jest podświetlonych na Zielono.

 155
Author: Daniel Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-30 00:41:32

To jest stare pytanie i jest to nieco subtelnie wspomniane w innych postach, ale wyjaśnienie, które sprawiło, że to kliknięcie dla mnie jest takie, że non fast forward merges będzie wymagało osobnego commita.

 33
Author: Parris Varney,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-02 19:56:06

Strategie Scalania

  • Explicit, non fast-forward merge
  • Implicit poprzez rebase lub fast-forward merge
  • Squash on merge

Tutaj wpisz opis obrazka

Tutaj wpisz opis obrazka

Tutaj wpisz opis obrazka

Tutaj wpisz opis obrazka

 9
Author: Premraj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-04 02:21:15