자식에서 병합을 미리 볼 수 있습니까?


397

git 브랜치 (예 : 메인 라인)가 있고 다른 개발 브랜치에 병합하고 싶습니다. 아니면 내가합니까?

이 분기를 실제로 병합할지 여부를 결정하기 위해 병합이 수행 할 작업에 대한 미리보기를보고 싶습니다. 적용되는 커밋 목록을 볼 수있는 기능이있는 것이 좋습니다.

지금까지 최고의 I는 가지고 올 수 merge --no-ff --no-commit다음과 diff HEAD.


17
난 그냥 거라고 git mergegit reset --keep HEAD@{1}나는 결과가 마음에 들지 않으면.
Jan Hudec

3
diff로 커밋 목록을 볼 때 반드시 전체 이야기를 들려주는 것은 아닙니다. 병합이 사소한 것이 아니며 특히 충돌이있는 경우 병합의 실제 결과는 약간 흥미로울 수 있습니다.
Cascabel

2
당신의 원래 방법은 정확히 그렇게합니다. 내 의견의 요점은 개별 diff를 보는 것이 모두 훌륭하고 훌륭하지만 복잡한 병합이 있으면 병합 된 모든 커밋이 독립적으로 훌륭하더라도 놀라운 결과가 나올 수 있다는 것입니다.
Cascabel

2
@Jan : 몇 가지 이유로 도움말이 git reset --keep HEAD@{1}반환 fatal: Cannot do a keep reset in the middle of a merge.되었습니까?
moey

3
--previewgit-merge에 옵션 이없는 이유는 무엇 입니까?
Gaui

답변:


283

나에게 가장 적합한 솔루션 은 병합을 수행하고 충돌이있는 경우 중단하는 것 입니다. 이 특정 구문은 깨끗하고 단순합니다. 이것은 아래 전략 2 입니다.

그러나 현재 브랜치를 엉망으로 만들지 않거나 충돌의 존재와 상관없이 병합 할 준비가되지 않은 경우 새 브랜치를 생성하고 병합하십시오.

전략 1 : 안전한 방법 – 임시 지사를 합병 :

git checkout mybranch
git checkout -b mynew-temporary-branch
git merge some-other-branch

그렇게하면 충돌이 무엇인지보고 싶을 때 임시 브랜치를 버릴 수 있습니다. 병합을 "중지"할 필요가 없으며 작업으로 되돌아 갈 수 있습니다. 간단히 'mybranch'를 다시 체크 아웃하면 지점에 병합 된 코드 나 병합 충돌이 없습니다.

이것은 기본적으로 드라 이런입니다.

전략 2 : 합병을 원하지만 충돌이없는 경우에만

git checkout mybranch
git merge some-other-branch

자식이 충돌을보고하면 충돌이있는 경우 에만 다음을 수행 할 수 있습니다.

git merge --abort

병합이 성공하면 중단 할 수 없습니다 (재설정 만).

병합 할 준비가되지 않은 경우 위의 더 안전한 방법을 사용하십시오.

[편집 : 2016 년 11 월-대부분의 사람들이 "안전한 방법"을 찾고 있기 때문에 전략 1을 2로 바꿨습니다. 전략 2는 이제 병합에 처리 할 준비가되지 않은 충돌이있는 경우 병합을 중단 할 수 있습니다. 의견을 읽을 때는 명심하십시오!]


2
전략 +1. 병합 할 때 정확히 어떤 내용이 표시되는지를 나타내는 임시 브랜치. 전략 1은이 특별한 경우를 피하려고하는 것입니다.
Gordolio

2
보다 안전한 전략이 먼저 이루어 지도록 전략을 바꾸는 것이 좋습니다 (제 정신 훈련이 다가옵니다. 대부분의 사람들은 "사퍼"라는 단어의 명확한 사용에도 불구하고 최선의 선택이 첫 번째 옵션이라고 가정 할 것입니다). 일.
paxdiablo 2016 년

6
당신은 할 수 git merge --no-ff --no-commit직접 변경 사항을 적용하지 않으려면. 이것은 다른 지점에 대한 "필요"를 제거하여 변경 사항을 조금 더 쉽게 검토 할 수있게합니다.
Gerard van Helden

그리고 당신이 전혀 병합하고 싶지 않다고 결정하고 실제로 더 많은 코드를 작성한 다음 지점에 커밋하여 지점을 테스트 서버에 배치 할 수 있다면 여전히 git merge --no-ff --no-commit? 를 되돌릴 필요가 없습니까? 아직도 할 수있을 것 같아git merge --abort당신이 보는 것을 좋아하지 않는다면 후에도 합니까? 병합으로 인해 충돌이 발생하지 않습니까?
Kasapo

대부분의 사람들은 복사하여 붙여 넣기를하고 너무 많이 생각하지 않습니다. 따라서 전략 1의 경우 임시 로컬 브랜치에서 병합을 중단 git reset --hard HEAD한 다음 다른 브랜치를 체크 아웃 git checkout <different branch name>하고 임시 브랜치를 삭제하는 방법을 추가 할 수도 있습니다 git delete -b <name of temporary branch>.
user3613932

400
  • git log ..otherbranch
    • 현재 분기로 병합 될 변경 목록
  • git diff ...otherbranch
    • 공통 조상 (병합베이스)에서 병합 될 대상의 헤드까지 차이 두 개의 점과 비교하여 특별한 의미를 갖는 세 개의 점을 주목 하십시오 (아래 참조).
  • gitk ...otherbranch
    • 마지막으로 병합 된 이후 브랜치의 그래픽 표현.

빈 문자열은을 암시 HEAD하므로 ..otherbranch대신 HEAD..otherbranch.

두 개의 점과 세 개의 점은 수정본 (log, gitk 등)을 나열하는 명령과 diff의 의미가 약간 다릅니다. 로그 및 기타의 경우 두 개의 점 ( a..b)은 들어 b있지만없는 모든 것을 의미 a하고 세 개의 점 ( a...b)은 a또는b 합니다. 그러나 diff는 두 가지 수정으로 작동하며 두 개의 점으로 표시되는 더 간단한 경우 ( a..b)는 a~ 와의 간단한 차이 b이며 세 개의 점 ( a...b)은 공통 조상과 b( git diff $(git merge-base a b)..b)의 차이를 의미 합니다.


7
세 번째 점은 내가 놓친 부분이었습니다. 감사합니다! . 로그 방식은 잘 또한, -p --reverse ..otherbranch가에 병합 될 것입니다 무엇을 볼 수있는 좋은 방법처럼 보인다 로그인 작품
Glenjamin

1
나는 git checkout master이것을 시도하기 전에 실종되었다 . 왜 모든 변경 사항을
덮어 쓰게 될지 궁금했습니다

5
git show ..otherbranch현재 브랜치로 병합 될 변경 및 diff 목록을 표시합니다.
Gaui

4
이것은 특히 체리 픽에 대해 완전히 정확하지는 않습니다.
void.pointer

2
@ void.pointer, git은 보통 병합에서 체리 픽을 다루지 않으므로 여기에서도 마찬가지입니다. 병합 전략을 작성할 수는 있지만 내가 아는 한 결코 그렇지 않았습니다.
Jan Hudec

19

당신이 나와 같다면을 찾는 것입니다 svn update -n. 다음은 트릭을 수행하는 것으로 보입니다. git fetch로컬 리포지토리와 비교할 적절한 업데이트가 있도록 먼저 수행해야합니다 .

$ git fetch origin
$ git diff --name-status origin/master
D       TableAudit/Step0_DeleteOldFiles.sh
D       TableAudit/Step1_PopulateRawTableList.sh
A       manbuild/staff_companies.sql
M       update-all-slave-dbs.sh

또는 머리에서 리모컨으로 diff를 원할 경우 :

$ git fetch origin
$ git diff origin/master

IMO이 솔루션은 "병합 후 중단"을 제안하는 최고의 솔루션보다 훨씬 쉽고 오류가 적습니다 (따라서 훨씬 덜 위험합니다).


1
이어야 $ git checkout target-branch하고 그때 $ git diff --name-status ...branch-to-be-merged(3 개의 점이 필수적이므로 그대로 입력)
Lu55

한 가지 빠진 점은 충돌이있는 파일을 보여주지 않습니다. 브랜치에서 수정되었지만 충돌없이 병합 할 수있는 파일과 동일한 "M"마커가 있습니다.
peterflynn

어쩌면 2012 년에는 상황이 달라졌지만 요즘 병합 중단은 매우 신뢰할 수있는 것처럼 보이므로 지금은 이것을 훨씬 쉽고 오류가 적은 경향이 있다고 생각하지 않습니다.
David Z

8

여기에 대부분의 답변은 깨끗한 작업 디렉토리와 여러 대화 형 단계 (스크립팅에 좋지 않음)가 필요하거나 모든 경우에 작동하지 않습니다 (예 : 대상 분기에 현저한 변경 사항을 이미 가져온 과거 병합 또는 체리 픽 같은.

master브랜치 develop로 합병 하면 브랜치 에서 어떤 변화가 일어날 지 실제로 보려면 :

git merge-tree $(git merge-base master develop) master develop

그것은 배관 명령이기 때문에, 당신이 의미하는 바를 추측하지 않으므로 명시 적이어야합니다. 또한 출력물을 채색하거나 호출기를 사용하지 않으므로 전체 명령은 다음과 같습니다.

git merge-tree $(git merge-base master develop) master develop | colordiff | less -R

https://git.seveas.net/previewing-a-merge-result.html

(링크에 David Normington에게 감사드립니다)

추신:

병합 충돌이 발생하면 다음과 같이 출력에 일반적인 충돌 마커와 함께 표시됩니다.

$ git merge-tree $(git merge-base a b ) a b 
added in both
  our    100644 78981922613b2afb6025042ff6bd878ac1994e85 a
  their  100644 61780798228d17af2d34fce4cfbdf35556832472 a
@@ -1 +1,5 @@
+<<<<<<< .our
 a
+=======
+b
+>>>>>>> .their

@dreftymac 사용자는 좋은 지적을합니다. 이것은 상태 코드에서 쉽게 파악할 수 없기 때문에 스크립팅에 적합하지 않습니다. 상황에 따라 충돌 마커가 크게 다를 수 있으므로 (삭제 및 수정 등) 그 리핑하기가 어렵습니다. 조심하십시오.


1
@hraban 이것은 정답처럼 보이지만 여전히 누락 된 요소가 하나 있습니다. 이 방법을 사용하려면 충돌 마커가 있는지 확인하기 위해 출력을 "안구"해야합니다. true충돌 이 있거나 충돌 false이없는 경우 (예 : "안구"테스트 또는 사람의 개입이 필요하지 않은 부울 값) 단순히 반환하는 접근 방식이 있습니까 ?
dreftymac

1
@dreftymac는 그 효과에 대해 아무것도 찾을 수 없습니다. 당신은 같은 것을 사용할 수 git merge-tree ... | grep -q '^[a-z].*in both$' && echo conflict || echo safe to merge있지만 아주 까다 롭습니다. 아마도 사건을 잊고있을 것입니다. 대신 충돌 마커를 확인하고 싶습니까? 예를 들어 이것은 아마도 "삭제, 변경"스타일 충돌을 포착하지 못할 것입니다. (방금 확인했는데 충돌 마커도 표시되지 않으므로 여기에 안전하려면 세심한 정규식이 필요합니다)
hraban

1
less -R구성을 수정하지 않고 컬러 출력을 처리하는 데 사용 합니다.
Giacomo Alzetta

@GiacomoAlzetta에게 감사드립니다. 업데이트했습니다.
hraban

6

이미 변경 사항을 가져 왔으면 가장 좋아하는 것은 다음과 같습니다.

git log ...@{u}

그래도 git 1.7.x가 필요합니다. 이 @{u}표기법은 업스트림 브랜치의 "약칭"이므로보다 다재다능합니다 git log ...origin/master.

참고 : zsh 및 확장 글 로그를 사용하는 경우 다음과 같은 작업을 수행해야합니다.

git log ...@\{u\}

6

기존 답변에 추가하여, 병합하기 전에 diff 및 / 또는 로그를 표시하기 위해 별명을 작성할 수 있습니다. 많은 답변 fetch은 병합을 "미리보기"전에 먼저 수행 해야하는 것을 생략합니다 . 이것은이 두 단계를 하나로 결합하는 별칭입니다 (mercurial의 hg incoming/ 와 유사한 것을 모방 outgoing)

따라서 " git log ..otherbranch"를 기반으로 다음을 추가 할 수 있습니다 ~/.gitconfig.

...
[alias]
    # fetch and show what would be merged (use option "-p" to see patch)
    incoming = "!git remote update -p; git log ..@{u}"

대칭의 경우 다음 별명을 사용하여 푸시하기 전에 커미트되고 푸시되는 대상을 표시 할 수 있습니다.

    # what would be pushed (currently committed)
    outgoing = log @{u}..

그런 다음 " git incoming"를 실행 하여 많은 변경 사항 git incoming -p을 표시 하거나 " "를 사용하여 패치 (예 : "diff"), " git incoming --pretty=oneline"를 간략하게 요약 할 수 있습니다. 그런 다음 " git pull" 실제로 병합합니다. (단, 이미 가져 왔으므로 병합을 직접 수행 할 수 있습니다.)

마찬가지로 " git outgoing"는 " "을 (를) 실행하면 푸시 될 내용을 표시합니다 git push.


3

git log currentbranch..otherbranch병합을 수행하면 현재 분기로 갈 커밋 목록을 제공합니다. 커밋에 대한 세부 정보를 제공하는 일반적인 로그 인수는 더 많은 정보를 제공합니다.

git diff currentbranch otherbranch하나가 될 두 커밋 사이의 차이점을 알려줍니다. 이것은 병합 될 모든 것을 제공하는 diff가 될 것입니다.

도움이 되겠습니까?


2
사실, 틀렸다. currentbranchgit log otherbranch..currentbranch 의 커밋 목록을 제공합니다 . 은 당신이 원하는 것은 병합 머리에 병합베이스에서 DIFF이기 때문에 당신이 그것을 할 수 있습니다 쓸모없는만큼 관한 현재의 팁에에 - 수 - 병합 된 버전에서 diff를 제공합니다. git diff otherbranch currentbranch
얀 후덱

감사. 나는 나무의 이름을 바꿨다.
Noufal Ibrahim

3

풀 요청-이미 제출 된 아이디어를 대부분 사용했지만 자주 사용하는 아이디어는 (특히 다른 개발자의 경우) 풀 요청을 수행하여 가져 오기 전에 병합의 모든 변경 사항을 검토하는 편리한 방법을 제공합니다 장소. 나는 GitHub가 자식이 아니라는 것을 알고 있지만 확실히 편리합니다.


2

실제로 버림 방식으로 병합을 수행하지 못한다면 (카 사포의 답변 참조) 신뢰할만한 방법이없는 것 같습니다.

말했듯이, 여기에는 거의 근접한 방법이 있습니다.

git log TARGET_BRANCH...SOURCE_BRANCH --cherry

이것은 어떤 커밋이 병합을 할 것인지에 대한 공정한 표시를 제공합니다. diff를 보려면을 추가하십시오 -p. 중 하나를 추가, 파일 이름을 확인하려면 --raw, --stat, --name-only,--name-status .

git diff TARGET_BRANCH...SOURCE_BRANCH접근 방식 의 문제 (Jan Hudec의 답변 참조)는 소스 분기에 교차 병합이 포함되어 있으면 대상 분기에서 이미 변경 사항에 대한 차이점을 볼 수 있다는 것입니다.


1

어쩌면 이것이 당신을 도울 수 있습니까? git-diff- tree-두 개의 트리 객체를 통해 발견 된 블롭의 내용과 모드를 비교합니다


1

충돌하는 파일을 검토하기위한 전구체로 git merge 명령을 사용하고 싶지 않습니다. 병합을하고 싶지 않고 병합하기 전에 잠재적 인 문제를 식별하고 싶습니다. 자동 병합이 나에게서 숨길 수있는 문제입니다. 내가 찾고있는 해결책은 git이 두 가지 분기에서 변경된 파일 목록을 공통 조상을 기준으로 나중에 병합 할 방법입니다. 해당 목록을 확보 한 후에는 다른 파일 비교 도구를 사용하여 더 자세히 조사 할 수 있습니다. 여러 번 검색했지만 여전히 네이티브 git 명령에서 원하는 것을 찾지 못했습니다.

다른 누군가를 도울 수 있도록 내 해결 방법이 있습니다.

이 시나리오에는 마지막 프로덕션 릴리스 이후 많은 변경 사항이있는 QA라는 지점이 있습니다. 우리의 마지막 프로덕션 릴리스에는 "15.20.1"태그가 붙어 있습니다. QA 지점으로 병합하려는 new_stuff라는 다른 개발 지점이 있습니다. QA와 new_stuff는 모두 15.20.1 태그를 "추적"(gitk에 의해보고 된) 커밋합니다.

git checkout QA
git pull
git diff 15.20.1 --name-only > QA_files
git checkout new_stuff
git pull
git diff 15.20.1 --name-only > new_stuff_files
comm -12 QA_files new_stuff_files

다음은 이러한 특정 파일을 타겟팅하는 데 관심이있는 몇 가지 토론입니다.

Git 병합을 어떻게 신뢰할 수 있습니까?

/software/199780/how-far-do-you-trust-automerge

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