git이 기본적으로 빨리 감기를 수행하는 이유는 무엇입니까?


641

수은에서 온 지점을 사용하여 기능을 구성합니다. 당연히, 나는이 역사를 나의 역사에서도보고 싶다.

git을 사용하여 새 프로젝트를 시작하고 첫 번째 기능을 마쳤습니다. 기능을 병합 할 때 git이 빨리 감기를 사용한다는 것을 깨달았습니다. 즉, 가능한 경우 변경 사항을 마스터 분기에 직접 적용하고 분기를 잊어 버렸습니다.

미래를 생각하기 위해 : 나는이 프로젝트에서 일하는 유일한 사람입니다. git의 기본 접근법 (앞으로 빨리 병합)을 사용하면 내 역사에 하나의 거대한 마스터 브랜치가 생길 것입니다. 아무도 내가 모든 기능에 대해 별도의 브랜치를 사용했음을 알지 못합니다. 결국에는 거대한 마스터 브랜치 만 갖기 때문입니다. 전문가답지 않습니까?

이 추론으로, 나는 빨리 병합을 원하지 않으며 이것이 왜 기본인지 알 수 없습니다. 그것에 대해 좋은 점은 무엇입니까?


38
참고 : sandofsky.com/blog/git-workflow.html 도 참조 no-ff하고 "체크 포인트 커밋"을 사용하여 이등분이나 비난을 피하는 ' '는 피하십시오 .
VonC

15
한 사람의 프로젝트에서 git을 사용하여 후회합니까?
HaveAGuess

27
절대적으로하지! 내 작업 폴더에는 git을 사용하는 7 명의 1 인 프로젝트가 있습니다. 나는이 질문을 한 이후 많은 프로젝트를 시작했으며 모든 프로젝트는 git을 통해 버전이 지정되었습니다. 내가 아는 한, git 및 mercurial 만 로컬 버전 관리를 지원합니다. 이것은 익숙해지기 때문에 나에게 필수적입니다. 설정하기가 쉽고 항상 전체 역사를 가지고 있습니다. 진행중인 작업 코드를 방해하지 않고 커밋 할 수 있기 때문에 그룹 프로젝트의 경우 훨씬 더 좋습니다. 또한 github을 사용하여 git이 필요한 일부 프로젝트 (예 : micro-optparse)를 공유합니다.
Florian Pilz

7
@Cawas는 사실 -no-ff좋은 아이디어는 아니지만 메인 브랜치에서 단 하나의 커밋 만 기록하면서 기능 내부 히스토리를 유지하는 데 도움이 될 수 있습니다. 메인 브랜치에서 때때로 진행될 때 긴 기능 히스토리에 적합합니다.
VonC

12
그건 그렇고, 당신의 질문에 "[선형 브랜치 히스토리]가 전문가가 아닌 것처럼 보입니까?". 기본값으로 소스 코드 시스템을 사용하는 것에 대해서는 전문가가 아닙니다. 이것은 전문성에 관한 것이 아닙니다. 이것은 어떤 브랜치 철학을 구독할지 결정하는 것입니다. 예를 들어 @VonC는 sandofsky의 기사와 연결되어 빠른 접근 방식을 우수한 접근 방식으로 사용합니다. 옳고 그른 것이 아니라 다른 맥락에 대한 다른 철학.
Marplesoft

답변:


718

빨리 감기 병합은 단기 브랜치에 적합하지만보다 복잡한 히스토리 에서는 빨리 감기가 아닌 병합을 통해 히스토리를 이해하기 쉽고 커밋 그룹을 쉽게 되돌릴 수 있습니다.

경고 : 빨리 감기를하지 않으면 부작용이 발생할 수 있습니다. https://sandofsky.com/blog/git-workflow.html을 검토 하고 "체크 포인트 커밋"으로 'no-ff'를 피하고 이등분이나 비난을 깨뜨리고 기본 접근 방식인지 신중하게 고려하십시오 master.

대체 텍스트
( nvie.com , Vincent Driessen의 " Git 분기 모델 성공 "게시 )

개발에 완성 된 기능 통합

완성 된 기능을 개발 지점으로 병합하여 다음 릴리스에 추가 할 수 있습니다.

$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff myfeature
Updating ea1b82a..05e9557
(Summary of changes)
$ git branch -d myfeature
Deleted branch myfeature (was 05e9557).
$ git push origin develop

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

Jakub Narębski설정에 대해 언급 했습니다 .merge.ff

기본적으로 Git은 현재 커밋의 자손 인 커밋을 병합 할 때 추가 병합 커밋을 만들지 않습니다. 대신, 현재 분기의 끝이 빨리 감 깁니다.
로 설정 false되면이 변수는 Git에게 이러한 경우 추가 병합 커밋을 생성 --no-ff하도록 명령합니다 (명령 줄에서 옵션 을 제공하는 것과 동일 ).
' only'로 설정하면 이러한 빨리 감기 병합 만 허용됩니다 ( --ff-only명령 행에서 옵션 을 제공하는 것과 동일 ).


다음과 같은 이유로 빨리 감기가 기본값입니다.

  • 수명이 짧은 브랜치는 Git에서 생성하고 사용하기가 매우 쉽습니다.
  • 단기 브랜치는 종종 해당 브랜치 내에서 자유롭게 재구성 할 수있는 많은 커밋을 분리합니다.
  • 이러한 커밋은 실제로 메인 브랜치의 일부입니다. 일단 재구성되면 메인 브랜치는 빨리 포함됩니다.

그러나 하나의 주제 / 기능 분기에서 반복 워크 플로우를 예상하는 경우 (즉, 병합 한 다음이 기능 분기로 돌아가서 커밋을 추가하십시오) 주 분기에 병합 만 포함시키는 것이 좋습니다. 기능 브랜치의 모든 중간 커밋.

이 경우, 이런 종류의 구성 파일 설정을 끝낼 수 있습니다 .

[branch "master"]
# This is the list of cmdline options that should be added to git-merge 
# when I merge commits into the master branch.

# The option --no-commit instructs git not to commit the merge
# by default. This allows me to do some final adjustment to the commit log
# message before it gets commited. I often use this to add extra info to
# the merge message or rewrite my local branch names in the commit message
# to branch names that are more understandable to the casual reader of the git log.

# Option --no-ff instructs git to always record a merge commit, even if
# the branch being merged into can be fast-forwarded. This is often the
# case when you create a short-lived topic branch which tracks master, do
# some changes on the topic branch and then merge the changes into the
# master which remained unchanged while you were doing your work on the
# topic branch. In this case the master branch can be fast-forwarded (that
# is the tip of the master branch can be updated to point to the tip of
# the topic branch) and this is what git does by default. With --no-ff
# option set, git creates a real merge commit which records the fact that
# another branch was merged. I find this easier to understand and read in
# the log.

mergeoptions = --no-commit --no-ff

OP는 주석에 다음을 추가합니다.

나는 [short-lived] 브랜치에 대해 약간의 의미가 있다고 생각하지만, 기본 동작으로 만드는 것은 git이 종종 [short-lived] 브랜치를 가지고 있다고 가정한다는 것을 의미합니다. 합리적?

Jefromi 답변 :

브랜치의 수명은 사용자마다 크게 다르다고 생각합니다. 그러나 숙련 된 사용자들 사이에서 더 짧은 수명을 갖는 경향이있을 것입니다.

저에게 단기 브랜치는 특정 작업을보다 쉽게하기 위해 (기반, 가능성 또는 빠른 패치 및 테스트) 만들기 위해 만든 브랜치입니다 . 완료되면 즉시 삭제합니다.
이는 분기 된 주제 분기로 흡수 될 가능성 높으며 주제 분기는 하나의 분기로 병합됩니다. 주어진 기능을 구현하는 일련의 커밋을 만들기 위해 내가 내부적으로 무엇을했는지 알 필요가 없습니다.

더 일반적으로 다음을 추가합니다.

실제로 개발 워크 플로 에 따라 다릅니다 .

  • 선형 인 경우 하나의 분기가 의미가 있습니다.
  • 기능을 분리하여 장기간 작업하고 반복적으로 병합해야하는 경우 여러 브랜치가 의미가 있습니다.

" 언제 분기해야합니까? " 참조하십시오.

당신은 의욕 가지 모델을 고려할 때 실제로, 그것의 핵심에 하나의 저장소 당 지점 (당신이 만들 수 있지만 익명 머리, 북마크, 심지어 이름을 가지 )
을 참조하십시오 "- 비교 및 대비 힘내과 의욕은" .

Mercurial은 기본적으로 익명의 경량 코드 라인을 사용하는데, 그 용어로 "헤드"라고합니다.
Git은 경량 저장소를 사용하여 원격 저장소의 분기 이름을 원격 추적 분기 이름에 매핑하기 위해 인젝 티브 매핑을 사용합니다.
힘내는 당신에게 지점의 이름을 지정하도록 강요합니다 ( " 분리 된 HEAD " 라고 불리는 하나의 이름없는 지점을 제외하고 ), 그러나 이것은 주제 지점 워크 플로와 같은 지점이 많은 워크 플로에서 더 효과적이라고 생각합니다. 단일 저장소 패러다임의 여러 분기.


와아, 그것은 빠르다. ;) --no-ff 옵션에 대해서는 알고 있지만 기능을 망쳐 놓은 후에 만 ​​빨리 찾을 수 있습니다. 나는 짧은 살아있는 지점에 대해 약간의 의미가 있다고 생각하지만 기본 동작을 만드는 것은 git이 가장 짧은 살아있는 지점을 가지고 있다고 가정한다는 것을 의미합니다. 합리적?
Florian Pilz

@Florian : 이것이 프로세스의 합리적인 관점이라고 생각합니다. 병합을 마스터로 관리하는 방법을 설정하는 구성의 예를 추가했습니다.
VonC

고맙게도 구성 파일은 그러한 문제를 피하는 데 도움이되어야합니다. :) "git config branch.master.mergeoptions '--no-ff'"를 사용하여이 구성을 로컬로만 적용
Florian Pilz

2
@BehrangSaeedzadeh : rebasing은 다른 주제입니다 (이 페이지에서 한 번 언급되지 않은) : feature지점을 공개 리포지토리로 푸시하지 않는 한 master원하는 횟수만큼 리베이스 할 수 있습니다 . 참조 stackoverflow.com/questions/5250817/...
VonC

4
@BehrangSaeedzadeh : 리베이스 자체는 역사를 선형 적으로 만들지 않습니다. 그것은이다 어떻게 당신이 당신의 변경 통합 feature에 지점 다시 master그 차종은 선형 또는하지의 역사를 말했다. 간단한 빨리 감기 병합은 선형으로 만듭니다. stackoverflow.com/questions/7425541/… 에서 언급했듯이, 빨리 감기 병합 전에 해당 feature브랜치 의 히스토리를 정리하고 중요한 커밋 만 남기는 것이 합리적 입니다.
VonC

42

VonC매우 포괄적 인 답변을 조금 확장 해 보겠습니다 .


먼저, 정확하게 기억한다면, 기본적으로 Git 이 빨리 감기병합 커밋 을 생성하지 않는다는 사실은 상호 풀이 두 저장소 를 동기화 하는 데 사용되는 단일 지점 "동일 저장소"를 고려한 것입니다 . "Git 사용자 매뉴얼"및 "예제 별 버전 관리"를 포함하여 대부분의 사용자 설명서에서 첫 번째 예제로 찾을 수 있습니다. 이 경우 pull을 사용하여 완전히 실현 된 분기를 병합하지 않고 다른 작업을 따라갈 수 있습니다. 저장소에 저장하고 저장하여 미래에 저장 한 동기화를 수행 할 때 일시적이고 중요하지 않은 사실을 원하지 않습니다.

기능 브랜치의 유용성과 단일 리포지토리에 여러 개의 브랜치가있는 것은 나중에 합병 지원이 잘되고 다양한 병합 기반 워크 플로우를 시도하는 VCS의 광범위한 사용으로 인해 나중에 나왔습니다. 예를 들어 Mercurial은 원래 "Mercurial : The Definitive Guide"의 이전 개정판에서 볼 수 있듯이 원래 저장소 당 하나의 브랜치 (원격 브랜치 추적을위한 익명의 팁 포함) 만 지원했습니다.


둘째, 기능 분기 를 사용하는 모범 사례 를 따르는 경우 , 즉 기능 분기는 모두 안정적인 버전 (일반적으로 마지막 릴리스부터)에서 시작하여 병합 할 기능 분기를 선택하여 포함 할 기능을 선택하고 선택할 수 있도록해야 합니다. 일반적으로 빠르게 진행되는 상황이 아닙니다 ...이 문제를 해결합니다. 단일 커밋을 '마스터'에 직접 넣지 않는다고 가정 할 때 첫 번째 분기를 병합 할 때 진정한 병합을 생성하고 빨리 감기하지 않도록 걱정해야합니다. 다른 모든 병합은 물론 앞으로 빨리 진행되지 않습니다.

HTH


안정적인 릴리스의 기능 분기 관련 : 다음 릴리스를 위해 개발중인 기능이 이미 개발하여 마스터에 병합 한 다른 기능의 변경 사항에 의존하는 경우 어떻게됩니까? 확실히 그것은 마스터 에서이 두 번째 기능 분기를 만들어야한다는 것을 의미합니까?
dOxxx

1
@dOxxx : 예. 예를 들어 한 분기가 다른 분기에 직접 구축되거나 이전에 마스터에 병합 한 후와 같은 예외가 있습니다.
Jakub Narębski
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.