git-병합 할 때 특정 커밋 건너 뛰기


200

나는 지금 약 1 년 동안 Git을 사용 해왔고 그것이 환상적이라고 생각하지만, 방금 프로젝트의 두 번째 버전을 시작했고 새로운 분기를 시작했습니다. 앞으로 일을 처리하는 가장 좋은 방법으로 조금 어려움을 겪고 있습니다.

master10 (v1의 경우)과 master20 (v2의 경우)이라고하는 두 가지가 있습니다. 브랜치 master10의 v1에서 버그를 수정하고 새로운 master20을 개발했습니다. 버그 수정을 할 때마다 master20을 확인하고 수행하여 v2에 병합합니다 git merge master10. 여태까지는 그런대로 잘됐다.

그러나 v2에서 원하지 않는 v1을 변경했지만 다른 버그 수정을 계속 병합하고 싶습니다. Git에게 특정 커밋 (또는 커밋 범위)을 건너 뛰라고 말하지만 앞으로도 다른 버그 수정을 병합하고 싶습니다.

나는 git rebase필요한 것일지도 모르지만 의사를 읽고 머리가 거의 폭발했다.

내가 원하는 것은 "git sync"명령과 같다고 생각한다. git에게 두 개의 브랜치가 현재 동기화되어 있고 앞으로이 동기화 지점의 커밋 만 병합한다는 것을 git에 알려준다.

도움을 주셔서 감사합니다.

답변:


289

예를 들어 "maint"브랜치의 커밋 대부분을 "master"로 병합하려는 경우이 작업을 수행 할 수 있습니다. 위에서 언급했듯이 일반적인 유스 케이스는 브랜치에서 모든 것을 병합하는 것입니다.하지만 때로는 다시 통합해서는 안되는 릴리스 버전을 변경 한 경우가 있습니다 (어쩌면 해당 코드는 이미 마스터로 대체되었습니다) 어떻게 표현합니까? 간다 ...

maint에 5 개의 변경 사항이 적용되었고 이들 중 하나 (maint ~ 3)가 다시 마스터로 병합되지 않아야한다고 가정 해 봅시다. 이 작업은 세 단계로 이루어집니다. 실제로 그 전에 모든 것을 병합하고, git에게 maint ~ 3이 병합되지 않은 경우에도 병합 된 것으로 표시 한 다음 나머지를 병합하도록 지시하십시오. 마술은 :

bash <master>$ git merge maint~4
bash <master>$ git merge -s ours maint~3
bash <master>$ git merge maint

첫 번째 명령은 번거로운 maint 커밋 전에 마스터로 모든 것을 병합합니다 . 기본 병합 로그 메시지는 "branch 'maint'(이전 부분)"을 병합하고 있음을 설명합니다.

두 번째 명령은 번거로운 maint ~ 3 커밋을 병합하지만 "-s ours"옵션은 git에게 특별한 "병합 전략"을 사용하도록 지시합니다. 실제로는 병합하려는 트리를 유지하고 커밋을 무시함으로써 작동합니다. ) 완전히 병합 중입니다. 그러나 여전히 부모로 HEAD 및 maint ~ 3을 사용하여 새 병합 커밋을 수행하므로 수정 그래프에 maint ~ 3이 병합되었다고 표시됩니다. 실제로 maint ~ 3 commit이 실제로 무시되고 있음을 설명하기 위해 -m 옵션을 사용하여 'git merge'를 사용하고 싶을 것입니다!

마지막 명령은 나머지 maint (maint ~ 2..maint)을 마스터로 병합하여 모두 다시 동기화됩니다.


5
커밋 병합을 연기 해야하는 경우 선택을 거의 건너 뛰고 건너 뛰고 (merge -s ours) 나중에 cherry-pick 명령을 사용하여 적용한다고 생각합니다. 커밋이 마스터에서 도달하면 다시 병합 할 수 없으므로 동일한 변경 사항을 두 번 병합하지 않는 것이 주요 git 목표 중 하나입니다.
araqnid

3
하위 브랜치 예제와 관련하여 : 하위 브랜치를 병합 한 후에는 내 게시물의 두 번째 단계 이후와 동일한 상황에있을 것으로 생각됩니다. 추가 분기를 작성해도 커미트 관계에 차이가 없습니다.
araqnid 2009

5
하나의 변경 사항 만 생략하고 싶은 경우, 단일 병합 만 수행 한 다음 3 개의 병합을 수행하는 대신 하나의 변경 세트를 되 돌리지 않는 이유는 무엇입니까? 그 결과 리포지토리에 커밋 된 변경 집합 수가 줄어들고보다 명확한 기록이 만들어집니다.
Mark Booth

3
커밋의 이름을 명시 적으로 지정하는 것이 더 쉬운 경우가 많습니다. 따라서 병합 할 브랜치의 git 로그를보고 커밋을 계산하는 대신 병합하지 않아야하는 커밋의 해시와 그 이전의 해시를 기록하면됩니다.
zwirbeltier

14
@MarkBooth : 건너 뛰려는 커밋은 병합하려는 브랜치와 크게 충돌 할 수 있습니다. 충돌을 수정 한 다음 변경 사항을
되돌리고

39

가장 논리적으로해야 할 IMHO는 모든 것을 병합 한 다음 git revert (commit_you_dont_want)를 사용하여 제거하는 것 입니다.

예:

git merge master
git revert 12345678

"무시"커밋이 여러 개 있거나 되돌리기 메시지를 편집하려는 경우 :

git merge master
git revert -n 123456
git revert -n abcdef
git commit -m "... Except commits 123456 and abcdef"

그러면 당신의 역사는 다음과 같습니다 :

| ... Except 123456 and abcdef
|\ Merge branch 'master' into 'your_branch'

이러한 "무시"커밋에만 관련된 충돌이있는 경우 다음을 사용할 수 있습니다.

git merge master -X ours

따라서 버전이 다른 버전보다 지속됩니다. 오류 메시지가 없어도 원치 않는 커밋은 충돌하지 않는 다른 변경 사항이있을 수 있기 때문에 원치 않는 커밋을 "복귀"할 수 있습니다.

"무시"커밋에만 관련되지 않은 충돌이있는 경우 수동으로 해결해야하며 되 돌리는 동안 다시 해결해야합니다.


2
나중에 되 돌린 커밋을 문제의 브랜치에 병합하려면 Git이 여전히 무시합니까?
Anriëtte Myburgh

@ AnriëtteMyburgh 당신은 나중에 "merge -s ours"전략으로는 쉽게 할 수없는 일로 되돌릴 커밋을 되돌릴 수 있습니다.
Lily Chung

감사합니다. 이것은 내가 마스터에서 원하지 않는 피처 브랜치와 마스터에서 원하지 않는 무리에 몇 가지 오래된 커밋이 필요한 것입니다. 좋고 깨끗합니다.
Vale Trujillo

17

커밋에는 조상이 포함됩니다. 이전 커밋을 병합하지 않고 커밋을 병합 할 수 없습니다.

물론 체리 픽을 선택할 수 있습니다. 유지 관리 모드에있는 브랜치가있는 경우 좋은 흐름입니다.


1
고마워, 체리 픽이 일을 할 것입니다. 내가 바랐던 것만 큼 좋지는 않지만 그렇게 할 것입니다.
Brad Robinson


3

기본적으로 @araqnid가 설명하는 프로세스를 래핑하는 내 프로젝트 에 대한 일종의 광고 입니다.

다음과 같은 GIT 흐름을 소개하는 도우미입니다.

  • 유지 보수 지점에서 개발자 / 마스터 지점으로의 보류중인 병합에 대한 일일 / 주간 알림이 있습니다.
  • 지점 관리자는 상태를 확인하고 모든 커밋이 필요한지 여부를 결정하고 일부 커밋을 차단하거나 개발자에게 자신을 차단하도록 요청합니다. 최종 유지 보수 지점은 업 스팀으로 병합됩니다.

프로젝트 페이지의 인용문 :

워크 플로에 따라 마스터 지점과 함께 유지 관리 또는 고객 별 지점을 가질 수 있습니다. 이 지점을 LTS 지점이라고도합니다.

종종 핫픽스가 버그가보고 된 지점으로 이동 한 다음 커밋이 다시 마스터 지점으로 병합됩니다.

일반적으로 모든 브랜치가 마스터와 완벽하게 동기화되도록하는 것입니다. 즉, 마스터에 모든 기능과 버그 수정이 포함되어 있는지 이해하기 위해 특정 브랜치와 마스터 간의 명확한 델타를 확인하려고합니다.

그러나 때때로 특정 커밋은 고객별로 다르며 다른 사용자가 볼 수 없기 때문에 원하지 않습니다. 또는 마스터 지사는 문제를 해결하기 위해 완전히 다른 접근 방식이 필요하거나 훨씬 더 문제가 더 이상 존재하지 않는다고 생각했습니다.

또한 마스터에서 유지 보수 지점으로 체리 픽을 선택하는 경우 결과 커밋은 마스터에서 차단됩니다.


0

master20에서는 원하지 않지만 master20에서는 원하는 변경 사항에 대한 세 번째 분기를 만듭니다. 항상 master10을 가장 안정적인 지점 인 "마스터"로 고려하십시오. 다른 모든 지점은 항상 동기화를 유지하려고합니다.


나는 그것이 효과가 있다고 생각하지만, 나는 이미이 상태에 빠졌고 세 번째 지점은 아마도 나를 더 혼란스럽게 할 것입니다. :)
Brad Robinson

0

이 경우 revert또는 대신 cherry-pick이 경우 건너 뛰는 변경 사항을 이전 변경 사항보다 오래된 것으로 간주하도록 git을 가져와야합니다.

그래서:

  1. 건너 뛰려는 커밋 전에 마지막 커밋을 병합하십시오. 물론 이것은 모든 커밋을 미리 병합합니다. git merge ccc
  2. 건너 뛰려는 커밋을 병합하십시오. git merge fff --no-commit
  3. 모든 병합을 준비하고, 모든 변경을 취소하고, 모든 변경을 취소하십시오. (아마도 이것에 대한 완벽한 명령이 있지만 UI 에서이 부분을 수행하려고하지만 방법을 알고 있습니다)
  4. 빈 병합을 완료하십시오 git merge --continue
  5. 건너 뛰려는 커밋을 병합합니다. git merge source-branch-head

4 단계 후에 git은 이미 커밋 한 것보다 분기를 더 오래 고려합니다.

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