스쿼시 풀 요청이 git의 병합 알고리즘을 위반합니까?


17

현재 git 코드를 관리하기 위해 VSTS를 사용하는 회사에서 일하고 있습니다. 브랜치를 병합하는 Microsoft의 "권장"방법은 "스쿼시 병합"을 수행하는 것입니다. 즉, 해당 브랜치에 대한 모든 커밋이 모든 변경 사항을 통합하는 하나의 새로운 커밋으로 스쿼시됩니다.

문제는 한 백 로그 항목에 대해 한 분기에서 일부 변경을 수행 한 다음 즉시 다른 백 로그 항목에 대해 다른 분기에서 변경을 시작하려는 경우 해당 변경은 첫 번째 분기의 변경 세트에 따라 어떻게됩니까?

해당 백 ​​로그 항목에 대한 브랜치를 만들고 첫 번째 브랜치를 기반으로 할 수 있습니다. 여태까지는 그런대로 잘됐다. 그러나 두 번째 분기에 대한 풀 요청을 만들 때가되면 첫 번째 분기가 이미 마스터로 병합되었으며 스쿼시 병합으로 수행 되었기 때문에 git은 많은 충돌을 표시합니다. 이것은 git이 두 번째 브랜치를 기반으로 한 원래 커밋을 보지 못하기 때문에 하나의 큰 스쿼시 병합을 보았 기 때문에 두 번째 브랜치를 병합하기 위해 마스터로 첫 번째 브랜치의 모든 커밋을 재생하려고합니다. 스쿼시 병합의 상단에 많은 충돌이 발생합니다.

그래서 내 질문은이 문제를 해결할 수있는 방법이 있습니까 (하나의 기능 지점을 다른 지점에서 기반을 두지 않고 내 워크 플로우를 제한하지 않는 것 이외) 또는 스쿼시 병합이 git의 병합 알고리즘을 깨뜨리는 것입니까?

답변:


15

Git으로 커밋

  • 불변이다
  • 유향 비순환 그래프를 형성합니다.

스 쿼싱은 커밋을 결합하지 않습니다. 대신, 여러 다른 커밋의 변경 사항으로 새로운 커밋을 기록합니다. 리베이스는 비슷하지만 커밋을 결합하지 않습니다. 기존 커밋과 동일한 변경 사항으로 새 커밋을 기록하는 것을 기록 다시 작성 이라고 합니다. 그러나 기존 커밋은 변경할 수 없으므로 "대체 이력 작성"으로 이해해야합니다.

병합은 공통 조상 커밋에서 시작하여 두 커밋 기록 (분기)의 변경 사항을 결합하려고합니다.

그래서 당신의 역사를 봅시다 :

                                 F  feature2
                                /
               1---2---3---4---5    feature1 (old)
              /
-o---o---o---A---o---o---S          master

A는 공통 조상, 1-5 원래 기능 분기, F 새 기능 분기 및 1-5와 동일한 변경 사항이 포함 된 스쿼시 커밋입니다. 보다시피, F와 S의 공통 조상은 A입니다. git에 관한 한, S와 1-5 사이에는 관계가 없습니다. 따라서 한쪽에 S를 사용하고 다른쪽에 1–5를 가진 feature2를 병합하면 충돌이 발생합니다. 이러한 갈등을 해결하는 것은 어렵지 않지만 불필요하고 지루한 작업입니다.

이러한 제약 때문에 병합 / 스 쿼싱을 처리하는 두 가지 방법이 있습니다.

  • 히스토리 다시 쓰기를 사용하면 동일한 변경 사항을 나타내는 여러 커밋이 발생합니다. 그런 다음 두 번째 기능 분기를 스 쿼쉬 된 커밋으로 리베이스 합니다.

                                     F  feature2 (old)
                                    /
                   1---2---3---4---5    feature1 (old)
                  /
    -o---o---o---A---o---o---S          master
                              \
                               F'       feature2
    
  • 또는 기록 다시 쓰기를 사용하지 않으면 추가 병합 커밋이 발생할 수 있습니다.

                                     F  feature2
                                    /
                   1---2---3---4---5    feature1 (old)
                  /                 \
    -o---o---o---A---o---o-----------M  master
    

    feature2와 master가 병합되면 공통 조상은 커밋 5가됩니다.

두 경우 모두 병합 노력이 필요합니다. 이 노력은 위의 두 가지 전략 중 어느 것을 선택 하느냐에 크게 좌우되지 않습니다. 그러나 확인하십시오

  • 지점은 수명이 짧아 마스터 지점에서 표류 할 수있는 거리를 제한합니다.
  • 정기적으로 마스터를 기능 분기로 병합하거나 분기를 동기화하도록 마스터에서 기능 분기를 리베이스하십시오.

팀에서 일할 때 누가 현재 무엇을하고 있는지 조정하는 것이 도움이됩니다. 이를 통해 개발중인 기능의 수를 작게 유지하고 병합 충돌 수를 줄일 수 있습니다.


2
feature1마스터에 스쿼시 병합 한 다음 feature2나중에 병합하려고 할 때 발생하는 문제를 해결하지 못하는 것 같습니다 . 이 경우, git feature1이 찌그러진 커밋 위에 커밋 을 다시 적용하려고 시도하는 동안 첫 번째 접근 방식으로 충돌이 발생하지 않는 반면, 두 번째 방법은 git이 커밋을 병합 할 필요가 없다는 것을 결정할 수있게합니까?
Jez

@Jez 바로 PR을 스쿼시 할 때 일어나는 일입니다. git clone지점에서 분기하고 관리자가 첫 번째 분기를 중단했기 때문에 최근에 OSS 프로젝트에서 PR을 수동으로 다시 작성해야했습니다 ( 리포지토리를 사용하여 변경된 파일을 복사하십시오!). 내 직업에서 그들은 또한 스쿼시 병합을 수행합니다. 즉, 기능 이 병합 될 때까지 기능 b에 의존 하는 기능 을 사용할 수 없습니다 . aa
계정

1
그리고 git이 설계된 것처럼 작동하지 않는 무언가가 실제로 성가신 파손이 아닙니까? Microsoft와 Github와 같은 다양한 조직이 실제로 이러한 스쿼시 병합을 권장하는 것을 보았습니다.
Jez

1
@Jez 원래 시나리오에서 커밋 1-5를 병합하면 S의 동일한 변경 사항과 충돌하기 때문에 feature2를 마스터로 병합 할 때 충돌이 발생합니다. 해결책은 feature2 (솔루션 1)를 리베이스하거나 스 쿼싱 / 리베이스를 사용하지 않는 것입니다. 모두 (솔루션 2).
amon

스쿼시 병합이 적합한 지 여부는 버전 관리 기록에 기록 할 대상에 따라 다릅니다. 기능 분기에 많은 WIP 커밋이있는 경우 스 쿼싱은 마스터 분기에서 전체 기능이 포함 된 하나의 큰 커밋을 수행합니다. 기능 분기의 모든 중간 커밋을 유지하려면 리베이스 또는 병합을 사용하십시오.
amon

11

스쿼시 병합은 스쿼시에 의해 제거 된 커밋이 포함 된 모든 분기에 대한 병합 알고리즘을 중단합니다. 달리 말하면, rebase는 바이러스 성입니다. 하나의 브랜치를 리베이스하는 경우 해당 브랜치에 종속 된 다른 브랜치를 리베이스해야합니다. rerere 를 사용하는 경우 로컬 리포지토리 에서 수동으로 해결 한 병합 충돌을 다시 수동으로 해결할 필요는 없지만 다른 사람이 해결 한 충돌에는 도움이되지 않습니다.

그렇기 때문에 여기에 기록되지 않은 규칙은 다른 사람이 기능 분기에 의존하지 않는 한 스쿼시하는 것이 좋습니다. 시간의 90 % 정도입니다. 그렇지 않으면 스트레이트 병합은 모든 사람이 문제를 피하는 데 도움이됩니다.


마스터 히스토리에서 스쿼시 커밋과 기능 브랜치를 모두 사용하여 별도의 스쿼시 전용 브랜치를 만들 수 있습니다. feature-xyz지점 이 있다고 가정하십시오 . 당신은 만들 수 있습니다 feature-xyz-squashed확약 같은에서 시작 지점 feature-xyz, 지점 git cherry-pick에서 커밋 feature-xyzfeature-xyz-squashed, 그들이 스쿼시 및 병합 feature-xyz-squashedmaster. feature-xyz그런 다음 병합하지 않아야합니다 . 때로는 위의 내용이 의미가 있습니다 (예 : 비밀번호를 넣은 커밋을 포함하지 않으려는 경우).
9000
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.