`git merge`와`git merge --no-ff`의 차이점은 무엇입니까?


답변:


1080

--no-ff플래그 방지 git merge그것이 당신의 전류가 감지 경우 "빨리 감기"실행에서 HEAD당신이 병합하려는 커밋의 조상이다. 빨리 감기는 병합 커밋을 구성하는 대신 git이 분기 포인터를 들어오는 커밋을 가리 키도록 이동시키는 경우입니다. 이것은 일반적으로 git pull로컬 변경없이 수행 할 때 발생합니다 .

그러나 때때로 특정 브랜치 토폴로지 (예 : 토픽 브랜치에서 병합하고 히스토리를 읽을 때 해당 방식으로 표시되도록하려는 경우)를 유지하기 때문에이 동작이 발생하지 않도록하려는 경우가 있습니다. 그렇게하기 위해서는, 당신은 통과 할 수 --no-ff플래그를하고 git merge것입니다 항상 빨리 감기 대신 병합을 구성.

마찬가지로, 명시 적으로 빨리 감기 를 위해 a를 실행 git pull하거나 사용 git merge하고 싶지만 빨리 감을 수 없으면 구제하려는 경우 --ff-only플래그를 사용할 수 있습니다 . 이런 식으로 git pull --ff-only생각하지 않고 정기적으로 무언가를 할 수 있으며 , 오류가 발생하면 다시 돌아가서 병합 또는 재베이스를 결정할 수 있습니다.


87
더 직접적으로 영업 이익의 질문에 대답하려면, 그들은 항상 다른 아니지만,이 경우, 그것은에서 분명 gitk또는 git log --graph비 빨리 감기 하나는 않았지만, 병합을 작성하지 않은 빨리 감기 병합 커밋.
Cascabel

11
ff를 피하는 이유를 확장하는 것이 좋을 것입니다. 저자가 "특정 브랜치 토폴로지"를 언급 한 경우 --no-ff의 경우 추가 병합 커밋이 병합의 마커 역할을한다는 것을 의미합니다. 전문가는 작성자 및 합병의 이름을 가진 명시 적 병합 마커입니다. 단점은 일련의 수렴 된 철도 트랙처럼 보이는 비선형 역사입니다. 가능한 심리적 병합 생각의 부작용으로 인해 더 이상 검토 과정에 관심을 잃어버린 참여자입니다 : blog.spreedly.com/2014/06/24/...
블라드

6
--no-ff개발 또는 개발하는 기능에서 마스터까지의 기능이 풀 요청을 병합하는 것과 비슷 하다고 말할 수 있습니까?
merlinpatt

9
@merlinpatt 물론입니다. GitHub에서 풀 요청을 병합하면 다음과 같습니다 --no-ff.
릴리 발라드

1
이것은 좋은 설명입니다. 사람, 깨끗한 git history가 왜 정말로 중요한지 이해하는 데 충분한 git 설명이 충분하지 않습니다. (나 포함!)
dudewad

1037

이 질문에 대한 그래픽 답변

다음은 사용에 대한 명확한 설명과 그래픽 일러스트 가있는 사이트 입니다 git merge --no-ff.

git merge --no-ff와 git merge의 차이점

내가 이것을 볼 때까지 나는 자식으로 완전히 길을 잃었다. 를 사용 --no-ff하면 기록을 검토하는 사람 이 작업 하기체크 아웃 한 지점 을 명확하게 볼 수 있습니다 . (그 링크는 github의 "네트워크"시각화 도구를 가리 킵니다.) 그리고 여기 에 삽화가있는 또 하나의 훌륭한 참고 자료 가 있습니다. 이 참조는 첫 번째 것을 보완하여 git에 익숙하지 않은 사람들에 더 중점을 둡니다.


나와 같은 신입생을위한 기본 정보

Git-guru가 아닌 나와 같은 경우 로컬 답변에서 문서를 삭제하지 않고 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

아래 : 설명을 포함한 실제 사용법.
참고 : 아래 출력이 차단됩니다. 자식은 매우 장황하다.

$ 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

위의 3 가지 사항에 유의하십시오.
1) 출력에서 ​​새 파일 추가를 포함하여 ECC 패키지 업그레이드의 변경 사항을 볼 수 있습니다.
2) 또한 /ecc이 변경과 독립적으로 삭제 한 두 개의 파일 ( 폴더에 없음)이 있습니다. 이 파일 삭제를 혼동하는 대신 파일 삭제 를 반영하기 위해 나중에 ecc다른 cleanup브랜치를 만들 것 입니다.
3) 워크 플로를 따르지 않았습니다! ECC를 다시 작동시키려는 동안 git을 잊어 버렸습니다.

아래 : git commit -am "updated ecc package"일반적으로 내가 포함하는 모든 것을하기보다는 /ecc폴더에 파일을 추가하고 싶었습니다 . 삭제 된 파일은 특별히 내 일부는 git add아니지만 git에서 이미 추적 되었으므로이 분기의 커밋에서 제거해야합니다.

$ 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 git@github.com:me/mywebsite.git
   8a0d9ec..333eff5  master -> master



위의 자동화를위한 스크립트

이 프로세스를 하루에 10 번 이상 사용한 후 명령을 실행하기 위해 배치 스크립트를 작성 했으므로 git_update.sh <branch> <"commit message">위의 단계를 수행 하는 데 거의 적합한 스크립트를 만들었습니다 . 해당 스크립트 의 요점 소스는 다음과 같습니다 .

대신에 git commit -am"생성 된"목록에서 파일을 선택 git status하여이 스크립트에 붙여 넣습니다. 이것은 수십 번의 편집 작업을했지만 변경 사항을 그룹화하는 데 도움이되는 다양한 지점 이름을 원했기 때문에 발생했습니다.


11
--no-ff옵션 과 병합 한 후에도 브랜치를 안전하게 삭제할 수 있습니까 ?
Andy Fleming

17
@DesignerGuy 예, 이전 분기를 안전하게 삭제할 수 있습니다. 분기 es를 특정 커밋에 대한 포인터로 생각하십시오.
Zyphrax

2
링크 된 페이지에서이 텍스트가 유용하다는 것을 알았습니다. --no-ff없이 "Git 히스토리에서 어떤 커밋 객체가 함께 기능을 구현했는지 확인할 수 없습니다. 모든 로그 메시지를 수동으로 읽어야합니다."
Lorne Laliberte

하나의 이미지는 항상 천 단어보다 최고입니다!
rupps December

1
그래픽은 두 번째 이미지의 기능 분기를 표시하지 않습니다. 왜 그렇지 않습니까? 아직도 존재하지 않습니까?
ADJenks

269

전략 병합

명시 적 병합 : 새 병합 커밋을 만듭니다. (이를 사용하면 얻을 수 있습니다 --no-ff.)

여기에 이미지 설명을 입력하십시오

빨리 감기 병합 : 새로운 커밋을 만들지 않고 빠르게 전달합니다.

여기에 이미지 설명을 입력하십시오

Rebase : 새로운 기본 레벨을 설정하십시오 :

여기에 이미지 설명을 입력하십시오

스쿼시 : 평평 해 지도록 힘을 가해 부수거나 쥐어 짜십시오.

여기에 이미지 설명을 입력하십시오


11
재미있는 그래픽이지만 실제로 --no-ff 사례를 보여주지 않으므로 여기서 질문에 대한 답을 얻지 못합니다.
Vib

22
여기에서 "병합"이라는 제목의 "명시 적 병합"은 ff가 아닌 병합입니다.
bkribbs

3
그래픽이 정말 도움이되었습니다
exexzian

2
말 당 질문에 대답하지 않지만이 그래픽은 훌륭합니다. UPVOTE!
소비에트 프론티어

3
그렇다면 Rebase와 빨리 감기 병합의 차이점은 무엇입니까?
ThanosFisherman

217

--no-ff옵션을 사용하면 빨리 감기 병합이 발생하지 않으며 새 커밋 개체가 항상 만들어 집니다. git이 기능 분기 히스토리를 유지하도록하려는 경우에 바람직 할 수 있습니다.             git merge --no-ff vs git merge 위의 이미지에서 왼쪽은 사용 후 git history git merge --no-ff의 예이고 오른쪽 git merge은 ff merge가 가능한 곳 의 사용 예입니다 .

편집 :이 이미지의 이전 버전은 병합 커밋에 대한 단일 부모 만 표시했습니다. 병합 커밋에는 git이 "기능 분기"및 원래 분기의 기록을 유지하는 데 사용하는 여러 개의 상위 커밋 이 있습니다. 여러 개의 상위 링크가 녹색으로 강조 표시됩니다.


3
녹색 화살표는 검은 색 화살표와 무엇을 나타 냅니까?
rtconner

11
녹색 화살표는 커밋과 둘 이상의 부모가있는 부모 사이의 링크를 나타냅니다. 일반 커밋 (검은 색)에는 부모가 하나만 있습니다.
Daniel Smith

9
@DanielSmith이 우아한 그래프를 어떻게 그리나요?
chancyWu

4
@chancyWu와 Adobe Illustrator 사용
Daniel Smith

회사에서는 모든 풀 요청이 --no-ff 옵션과 병합되는 것 같습니다. 이러한 상황에서 풀 요청을 작성하기 전에 리베이스하는 것이 여전히 타당합니까?
Nickpick

37

이것은 오래된 질문이며, 다른 게시물에서 약간 미묘하게 언급되었지만 저를 위해 클릭 한 이유는 빨리 감기아닌 병합에는 별도의 커밋이 필요하다는 것 입니다.


위의 답변에서 워크 플로우를 검토 하시겠습니까? 즉, 지금 내가 얻은 것보다 추가 커밋이 필요합니까? 감사.
Chris K

3
@ChrisK git merge --no-ff eccgit logfor 분기 마스터 에 단순히 추가 병합 커밋을 갖습니다 . 마스터가 커밋 ECC의 직접적인 조상을 가리키고 있지만 --no-ff 옵션을 지정하면 해당 병합 커밋을 강제로 만드는 경우 기술적으로 필요하지 않습니다. 제목 :Merge branch 'ecc'
Ankur Agarwal

훌륭한 요약! :)
에두아르

4

--no-ff 플래그는 빨리 감기를 통해 병합을 수행 할 수있는 경우에도 병합이 항상 새 커밋 객체를 생성하도록합니다. 이렇게하면 기능 분기의 히스토리 존재에 대한 정보가 유실되지 않으며 기능을 함께 추가 한 모든 커밋을 그룹화합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.