it-swarm.dev

왜 자식은 기본적으로 빨리 감기 병합을 수행합니까?

Mercurial에서 제공하는 기능을 구성하기 위해 브랜치를 사용합니다. 자연스럽게, 나는 역사에서이 작업 흐름을보고 싶다.

Git을 사용하여 새 프로젝트를 시작하고 첫 번째 기능을 완료했습니다. 이 기능을 병합 할 때 git는 빨리 감기를 사용한다는 것을 알았습니다. 즉, 가능한 경우 마스터 분기에 변경 사항을 적용하고 내 브랜치는 잊어 버렸습니다.

미래에 대한 생각 : 저는이 프로젝트를 진행하는 유일한 사람입니다. git의 기본 접근법 (빨리 감기 병합)을 사용하면 내 역사가 하나의 거대한 마스터 지점이됩니다. 결국 모든 기능에 대해 별도의 지점을 사용한다는 것을 아무도 모릅니다. 결국에는 거대한 마스터 지점 만 갖기 때문입니다. 전문가답지 않은데?

이러한 이유로, 나는 빨리 감기가 병합되는 것을 원하지 않으며 그것이 왜 디폴트인지 알 수 없다. 그것에 대해 얼마나 좋습니까?

628
Florian Pilz

빨리 감기 병합은 단기 브랜치에 적합하지만 복잡한 기록 에서 더 빨리 감기를 수행하면 기록을 더 쉽게 이해하고 그룹을 쉽게 되돌릴 수 있습니다. 커밋.

경고 : 빨리 감기가 아닌 경우에도 부작용이 발생할 수 있습니다. https://sandofsky.com/blog/git-workflow.html , "검사 점 커밋"으로 이등분 또는 비난을 겪는 'no-ff'는 피하고 master.의 기본 접근 방식인지 신중하게 고려해야합니다.

alt text
( 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 또한 mentionsconfig 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 답변 :

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

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

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

실제로 development workflow 에 따라 다릅니다.

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

" 언제 분기해야합니까? "참조

실제로 Mercurial 브랜치 모델을 고려할 때 해당 모델은 one 리포지토리 당 브랜치 에 있습니다 ( 익명의 머리, 북마크 및 심지어 지명 된 지점 )
"Git and Mercurial-비교 및 대조" 를 참조하십시오.

Mercurial은 기본적으로 익명의 경량 코드 라인을 사용하는데, 그 용어로 "헤드"라고합니다.
Git은 가벼운 이름의 브랜치를 사용하고, 원격 저장소의 브랜치 이름을 원격 추적 브랜치의 이름에 매핑하기 위해 인젝 티브 매핑을 사용합니다.
Git은 " detached HEAD "라는 상황 인 이름없는 단일 브랜치를 제외하고 브랜치의 이름을 "강제"합니다. 단일 저장소 패러다임의 여러 분기를 의미하는 주제 분기 워크 플로와 같이 분기가 많은 워크 플로에서 더 잘 작동합니다.

709
VonC

VonC매우 포괄적 인 답변 에서 조금 확장하겠습니다 :


먼저 올바르게 기억하면 기본적으로 Git이 fast-forward 경우 merge commits 를 만들지 않는다는 사실 mutual pull은 두 저장소를 동기화하기 위해 사용되는 단일 지점 "동일한 저장소"를 고려한 결과입니다 (워크 플로는 " Git 사용자 매뉴얼 "및"예제 별 버전 관리 "). 이 경우 pull을 사용하여 완전히 실현 된 분기를 병합하지 않고 다른 작업을 따라 잡기 위해이를 사용합니다. 저장소에 저장하고 저장하여 미래에 저장 한 동기화를 수행 할 때 일시적이고 중요하지 않은 사실을 원하지 않습니다.

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


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

HTH

41
Jakub Narębski