자식에서“우리”와“그들의”의 정확한 의미는 무엇입니까?


323

이것은 너무 기본적인 질문처럼 들릴지 모르지만 답변을 검색했으며 이전보다 더 혼란 스럽습니다.

내 지점을 다른 지점으로 병합 할 때 git에서 "우리"와 "그들의"는 무엇을 의미합니까? 두 가지 모두 "우리"입니다.

병합 충돌에서 "우리"는 항상 두 버전의 상단에 표시됩니까?

"우리"는 항상 병합이 시작될 때 HEAD가 가리키고 있던 지점을 참조합니까? 그렇다면 왜 "모두"가 "모호한"(우리 둘 다 기술적으로 우리의 것이기 때문에) "우리"와 같은 소유 대명사를 사용하는 대신 "현재 분기"와 같은 명확한 소유 참조를 사용하지 않겠습니까?

아니면 지점 이름을 사용하십시오 ( "우리"대신 "로컬 마스터"등)?

가장 혼란스러운 부분은 특정 지점의 .gitattributes 파일에 지정하는 것입니다. 에 말을 수 있습니다 테스트 지점 나는 다음과 같은 .gitattributes 파일이 있습니다 :

config.xml merge=ours

이제 체크 아웃하고 HEAD가 master 를 가리킨 다음 test 에서 병합 합니다. 이후 마스터 입니다 우리, 그리고 테스트 의 .gitattributes 그것도 영향을 미칠 것이다, 체크 아웃되지 않는 이유는 무엇입니까? 그것이 효과가 있다면, 주인 이 이제 우리의 것이기 때문에 , 어떻게 될까요?

답변:


374

혼란 스럽기 때문에 혼란스러워하는 것 같습니다. 상황을 악화시키기 위해 리베이스를 수행 할 때 우리 전체 / 그들의 물건이 역할을 바꿉니다 (거꾸로 됨).

궁극적으로시 git merge의 "우리"지사는 병합하고있는 지점을 말한다 :

git checkout merge-into-ours

"그들의"브랜치는 병합하고있는 (단일) 브랜치를 의미합니다 :

git merge from-theirs

"그들"과 "그들"은 어쨌든 "그들"이 아마도 당신의 것이더라도 "그들"은 당신이 달렸 때 당신 이 아니었던 것처럼 말이 됩니다 git merge.

실제 브랜치 이름을 사용하는 것은 꽤 멋지지만 더 복잡한 경우에는 다릅니다. 예를 들어 위 대신에 다음을 수행 할 수 있습니다.

git checkout ours
git merge 1234567

raw commit-ID로 병합하는 곳. 더 나쁜 것은, 당신은 심지어 이것을 할 수 있습니다 :

git checkout 7777777    # detach HEAD
git merge 1234567       # do a test merge

이 경우 관련된 브랜치 이름 이 없습니다 !

나는 여기에 약간의 도움이된다고 생각하지만 실제로 gitrevisions구문 에서는 충돌하는 병합 중에 인덱스의 개별 경로를 숫자로 참조 할 수 있습니다

git show :1:README
git show :2:README
git show :3:README

1 단계는 파일의 공통 조상이고 2 단계는 대상 분기 버전이며 3 단계는 병합하려는 버전입니다.


"우리"와 "그들의"개념이 rebase바뀌는 이유는 일련의 체리 픽을 익명 브랜치 (분리 된 HEAD 모드)로 수행하여 리베이스가 작동하기 때문입니다. 대상 브랜치는 익명 브랜치이며 머지-온 브랜치는 원래 (사전 리베이스) 브랜치입니다. "-우리의"는 익명의 하나의 리베이스가 구축되는 것을 의미하고 "-그들의"는 "우리의 브랜치가 기반을 둔"을 의미합니다. .


gitattributes 항목에 대해서는 다음 과 같은 효과가 있을 수 있습니다. "우리의"는 실제로 "단계 2 사용"을 의미합니다. 그러나 당신이 알다시피, 그것은 실제로 당시의 장소 가 아니기 때문에 그렇게 해서는 안됩니다. 여기에 영향을 미치지 합니다 ... 시작하기 전에 작업 트리에 복사하지 않으면 안됩니다.

또한, 이것은 우리와 그들 모두의 모든 용도에 적용되지만 일부는 전체 파일 수준에 있습니다 (-s ours 병합 전략, git checkout --ours병합 충돌시) 일부는 조각별로 조각으로 있습니다 ( -X ours또는 -X theirs-s recursive 병합). 어느 혼란을 도울 수 없습니다.

그래도 나는 이것들에 대한 더 좋은 이름을 찾지 못했습니다. 또 다른 질문에 대한 VonC의 답변 을 참조하십시오 . 여기서 git mergetool더 많은 이름을 도입하여 "로컬"및 "원격"이라고합니다!


28
+1. 리베이스 도중에 우리와 그들의 리버스에 대해서는 stackoverflow.com/a/2960751/6309stackoverflow.com/a/3052118/6309
VonC

1
두 가지는 서로 "합쳐진다". 병합이 발생하면 양쪽이 서로 "통합"됩니다. 양측 중 하나가 "무엇으로도 합병되지 않는다"고 말하는 것이 옳지 않다고 생각합니다. 관련된 브랜치 이름이없는 경우 (명시한대로) 커밋 이름이 있습니다 ( "ours"및 "thes"대신 "7777777 's"및 "1234567 's). 나는 rebase 동안 무슨 일이 일어나고 있는지 이해하고 전혀 혼란스럽지 않습니다. "HEAD"와 "incoming 's"는 항상 "HEAD"(분리 여부에 관계없이)가 있기 때문에 "우리"와 "그들"보다 더 잘 작동한다고 생각합니다.
CommaToast

15
나는 머리가 마음의 자리, 즉 정체성의 원천, 자기의 원천이기 때문에 HEAD가 가리키는 것이 무엇이든 "광산"( "우리의 것")이라고 생각하는 것이 조금 더 합리적이라고 생각합니다. 나는 나와 HEAD가 두 가지를 만든다고 생각한다. 더 이상 없다면 그것은 좋은 니모닉 장치 일 것입니다.
CommaToast

1
다시
말하지만

3
"이 경우 관련된 분기 이름이 없습니다!"... 대신 커밋 주석 / 해시를 사용해야합니다. 손을 잡을 수있는 것은 무엇이든. 실제로는 "우리"와 "그들"보다 낫습니다. 이 혼란이 얼마나 많은 개발 시간을 겪었는지 궁금합니다. C ++의 "가장 성가신 구문 분석"에 대한 자식의 대답)
재로드 스미스

49

Git 의 ' ours '는 git history의 권위있는 / 정규적인 부분을 가진 원래 작업 지점을 나타냅니다.

' 그들의 '은 리베이스 하기 위해 작품을 보유하고있는 버전을 나타냅니다. (현재 브랜치에서 재생되도록 변경) .

이 일을 (예 : 리베이스 인식하지 못합니다 사람들에게 교환 할 나타날 수 있습니다 git rebase) 실제로 (이다 보류 작업 취하고 그들의을 하다 정식 / 주요 역사에 재생하기 위해) 우리 우리가 리베이스하고 있기 때문에, 우리의 타사 작업으로 변경됩니다.

에 대한 문서 git-checkoutf303016커밋 당 Git> = 2.5.1에서 더 명확 해졌습니다 .

--ours --theirs

색인에서 경로를 체크 아웃 할 때 병합되지 않은 경로에 대해 2 단계 ( '우리') 또는 # 3 ( '그들의')을 확인하십시오.

참고 그 동안 git rebasegit pull --rebase, '우리'와 교환을 '그들의'가 나타날 수 있습니다; --ours변경 사항이 기반으로 --theirs하는 지점의 버전 을 제공하고 , 기반 이되는 작업을 보유한 지점의 버전 을 제공합니다.

이 때문입니다 rebase원격의 기록을 공유 정식 기록으로 처리하고 통합하려는 타사 작업으로 rebasing하는 지점에서 수행 한 작업을 일시적으로 처리하는 워크 플로에서 사용 입니다. rebase 동안 정식 역사의 골키퍼. 표준 이력의 보관 인으로서, 당신은 원격지의 이력을 ours"즉, 우리의 공유 된 정식 이력"으로보아야하고, 당신의 부지에서 theirs한 일 을 (즉, "그 위에 기여한 사람의 한 작품"으로) 볼 필요가 있습니다.

에 대한 git-merge 다음과 같은 방법으로 설명입니다 :

우리 것

이 옵션은 버전을 선호하여 충돌하는 덩어리를 자동으로 자동 해결합니다. 우리 측과 충돌하지 않는 다른 트리의 변경 사항은 병합 결과에 반영됩니다. 바이너리 파일의 경우 전체 내용이 우리 측에서 가져옵니다.

이것은 다른 트리에 포함 된 것을 보지 않는 병합 전략과 혼동되어서는 안됩니다. 그것은 다른 나무가 한 모든 것을 버리고, 우리의 역사는 그 안에 일어난 모든 것을 포함한다고 선언합니다.

그들의 것

이것은 우리의 반대입니다.

더 자세한 내용은 다음과 같습니다.

병합 메커니즘 ( git mergegit pull명령)을 통해 백엔드 병합 전략을 -s옵션 으로 선택할 수 있습니다. 일부 전략은 자체 옵션을 취할 수도 있으며, -X<option>인수는 git merge및 / 또는에 인수하여 전달할 수 있습니다 git pull.


따라서 때로는 혼란 스러울 수 있습니다.

  • git pull origin master-Xours우리 지역은 어디 -Xtheirs입니까?
  • git pull origin master -r여기서 -Xours그들의를 (원격)입니다, -Xtheirs우리이다

따라서 두 번째 예제는 첫 번째 예제와 반대입니다. 우리는 원격 지점 위에 분기를 리베이스하고 있기 때문에 시작 지점이 원격이며 변경 사항이 외부로 처리되기 때문입니다.

git merge전략 ( -X ours-X theirs) 과 유사합니다 .


2
이 답변이 유효한 옵션이 아닙니다 => "자식 병합 --ours"구식 인 것 같다
알렉산더 밀스

대답은 이야기하지 않았다 @AlexanderMills git merge하지만, git pullgit checkout예로서. 이 매개 변수를와 함께 git merge사용하려면을 사용해야합니다 -X ours. 에 --ours대한 구문을 계속 사용할 수 있습니다 git checkout. 나는 그 대답을 더 명확히했다.
kenorb

46

나는 이것이 대답되었다는 것을 알고 있지만,이 문제는 나를 기억하는 데 도움이되는 작은 참조 웹 사이트를 두 번이나 혼란스럽게 만들었다 : https://nitaym.github.io/ourstheirs/

기본 사항은 다음과 같습니다.

합병 :

$ git checkout master 
$ git merge feature

에서 버전을 선택하려면 다음을 수행하십시오 master.

$ git checkout --ours codefile.js

에서 버전을 선택하려면 다음을 수행하십시오 feature.

$ git checkout --theirs codefile.js

리베이스 :

$ git checkout feature 
$ git rebase master 

에서 버전을 선택하려면 다음을 수행하십시오 master.

$ git checkout --ours codefile.js

에서 버전을 선택하려면 다음을 수행하십시오 feature.

$ git checkout --theirs codefile.js

(물론 이것은 완전한 파일을위한 것입니다)


1
그 웹 사이트는 매우 유용합니다. 순서도 스타일과 색상으로 구분 된 단어를 사용하면 SO 답변보다 웹 사이트를 훨씬 쉽게 이해할 수 있습니다. 감사합니다.
Ron

10
  • 우리의 것 : 이것은 당신이 현재있는 지점입니다.
  • 그들의 것 : 이것은 당신의 행동에 사용되는 다른 지점입니다.

당신은 지점에 위치하도록하면 릴리스 / 2.5 당신은 지점 병합 기능 / 새로운 버튼을 그것에에 발견하면 해당 내용 릴리스 / 2.5은 무엇인가 우리가 발견으로 의미와 내용을 기능 / 새로운 버튼을 무엇 그들의 것이 의미 에. 병합 작업 중에는 매우 간단합니다.

대부분의 사람들 이 겪는 유일한 문제 는 리베이스 사건 입니다. 일반 병합 대신 리베이스를 수행하면 역할이 교체됩니다. 어떻게한다는거야? 음, 그것은 rebasing이 작동하는 방식에 의해서만 발생합니다. rebase가 다음과 같이 작동한다고 생각하십시오.

  1. 마지막 풀 이후에 수행 한 모든 커밋은 자신의 브랜치로 이동합니다 . 이름을 BranchX로 지정 하겠습니다 .
  2. 현재 지점의 헤드를 체크 아웃하여 로컬 변경 사항을 버리지 만 다른 지점이 해당 지점에 대해 푸시 한 모든 변경 사항을 검색합니다.
  3. 이제 BranchX의 모든 커밋 은 현재 브랜치에 새로운 것부터 순서대로 선택됩니다.
  4. BranchX 가 다시 삭제되어 기록에 표시되지 않습니다.

물론, 그것은 실제로 진행되고있는 것이 아니지만 그것은 나에게 좋은 마음 모델입니다. 2와 3을 보면 역할이 바뀌는 이유를 이해할 수 있습니다. 이 그래서 2로, 현재 지점은 변경 사항없이 서버에서 분기, 지금 우리 (당신이있는 지점). 당신이 당신의 현재 (이 아닌 다른 지점에 지금 변경 BranchX 따라서)와 (당신이 만든 변경 사항을 임에도 불구하고)이 변경되어 그들의 (액션에 사용되는 다른 분기).

즉, 병합하고 변경 사항을 항상이기려면 git에 항상 "우리"를 선택하라고 지시하지만 리베이스하고 모든 변경 사항을 항상이기려면 git에 항상 "그들의"를 선택하도록 지시하십시오.


3

나는 그것이 의미를 설명하지는 않지만 어느 것을 사용 해야하는지 상기시키기 위해 작은 이미지를 만들었습니다.

여기에 이미지 설명을 입력하십시오

그것이 도움이되기를 바랍니다!

추신 -에있는 링크도 수표를 부여 Nitay의 대답 🙂


3

다시 여기로 와야하므로 메모를 여기에 게시하겠습니다.

시나리오 1. 일반 개발자 : 귀하는 지점 master과 합병 할 수없고 feature지점 만 가지고 놀아야하는 개발자입니다 .

사례 1 : 주인은 왕이다. 새로운 종속성 업데이트가 포함되어 있고 약간의 변경 사항을 덮어 쓰려고하기 때문에 feature브랜치 를 새로 고치려고합니다 (= rebase to master) master.

git checkout master
git pull

git checkout feature
git rebase -X ours master

사례 2 : 당신은 왕입니다. feature브랜치를 master변경 사항 으로 리베이스하려고합니다 . 그러나 동료보다 더 많은 일을하고 자신의 변경 사항을 우선적으로 사용하려고합니다.

git checkout master
git pull

git checkout feature
git rebase -X theirs master

중요 : 일반 개발자는 rebase매일 아침 운동 / 커피와 같이 매일 좋아 하고 반복 해야합니다 .

시나리오 2. 합병 선생 : 팀 리더이며 다른 지점을 합병하고 합병 된 결과를 직접 마스터에게 전달하려고합니다. master변경할 지점입니다.

사례 1 : 마스터는 왕이다 타사 지점을 병합하려고하지만 master우선 순위입니다. feature당신의 선배가 한 지점입니다.

git checkout feature
git pull

git checkout master
git merge -X ours master

사례 2 : 새로운 변화가 왕이다 수석 개발자가 멋진 것을 발표 feature하고 master지점 의 이전 버전을 덮어 쓰려고 할 때 .

git checkout feature
git pull

git checkout master
git merge -X theirs master

기억 : 하나를 선택하기가 자정에 기억해야 할 master것입니다 ours항상. 그리고 theirsA는 feature그들의 행한 것을.


2

에서 git checkout의 사용 :

-2, --ours            checkout our version for unmerged files
-3, --theirs          checkout their version for unmerged files
-m, --merge           perform a 3-way merge with the new branch

병합 충돌을 해결하는 경우, 당신은 할 수있는 git checkout --theirs some_file, 그리고 git checkout --ours some_file각각의 현재 버전과 들어오는 버전에 파일을 재설정 할 수 있습니다.

당신이 한 경우 git checkout --ours some_file또는 git checkout --theirs some_file해당 파일의 3 방향 병합 버전으로 파일을 다시하고 싶은, 당신은 할 수 있습니다 git checkout --merge some_file.

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