Git pull 결과 커밋 로그에 불필요한 "Merge branch"메시지가 나타납니다.


110

저는 프로젝트에서 다른 개발자와 함께 작업하고 있으며 원격 저장소로 Github를 사용하고 있습니다. 저는 git 1.7.7.3을 사용하는 Mac에 있고, git 1.7.6을 사용하는 Windows에 있습니다.

이게 무슨 일이야

  1. 우리 중 한 명 (그를 개발자 A라고 부르겠습니다.하지만 어느 것이 문제가되지 않습니다)는 일련의 커밋을 GitHub에 푸시합니다.
  2. 다른 하나 (개발자 B)는 일부 로컬 커밋을 수행합니다.
  3. B는 git pull.
  4. B는 git push.
  5. 커밋 내역 로그를 보면 github.com:foo/bar의 Merge branch 'master'가 보입니다.

커밋 로그는 시간이 지남에 따라 "Merge branch"메시지로 흩어져 있으며 개발자 A가 변경 한 내용을 커밋하는 것으로 개발자 B도 표시합니다. 이 문제를 방지하기 위해 우리가 찾은 유일한 방법은 git pull --rebase3 단계에서 를 수행하는 것이었지만 리베 이싱이 어떤 부작용을 가져올 지 모르겠습니다. 다중 개발자 git repo에서 작업하는 것은 이번이 처음이므로 정상적인 동작입니까? 이 문제를 해결하는 방법에 대한 의견이 있으십니까?


2
당신과 함께 병합하지 않고 로그를 볼 수 있습니다git log --no-merges
wjandrea

답변:


88

당신이보고있는 커밋은 완벽하게 괜찮습니다. A가 pull효과적으로 실행 된 git fetch다음 git merge일반적으로를 실행할 때 병합이 발생합니다 git pull.

병합 대신 리베이스를 사용하는 대안이 가능하지만 일반적으로이를 피해야합니다. 리베이스를 사용하면 선형 기록을 유지할 수 있지만 원래 발생한 분기에 대한 모든 정보도 제거됩니다. 또한 현재 분기의 기록이 다시 작성되어 대상 분기 (귀하의 경우 원격)에 포함되지 않은 모든 커밋이 다시 작성됩니다. 재 작성된 커밋은 서로 다른 커밋이므로 다른 사람과 함께 개발할 때 많은 혼란을 야기 할 수 있습니다. 따라서 경험상 이미 푸시 된 커밋을 다시 작성 해서는 안됩니다 .

표시되는 커밋은 두 개 (또는 그 이상)의 분기를 결합하기위한 것입니다. 다른 작업을 수행하지 않고 여러 분기를 병합하는 커밋을 갖는 것은 완벽합니다. 사실 히스토리를 볼 때 분기를 결합하는 병합 커밋이있을 때 매우 명확합니다. 리베이스와 비교하여 병합을 사용하면 공존 한 실제 분기를 포함하여 개발 된 원래의 역사 를 효과적으로 볼 수 있습니다 .

짧게 말하면, 예, 커밋을 병합하는 것은 완벽하며 걱정할 필요가 없습니다.


2
아주 좋은 대답입니다. 일부 오픈 소스 프로젝트 기여 가이드 라인에서 추천 되었기 때문에 리베이스 스타일을 시도했는데 문제가 발생했습니다. 팀의 새로운 멤버도 마찬가지였습니다. 리베이스 옵션은 하루 종일 함께 작업하는 팀을위한 것이 아니라 패치를 제출하는 주요 기여자와 다른 기여자가있는 프로젝트에 적합하다고 생각합니다. 그들은 메인 리포지토리를 가져오고 풀 리퀘스트를 발행하기 직전에 변경 사항을 리베이스해야합니다.
Meligy

2
@sTodorov 새로운 변경 사항이 없으면 풀의 가져 오기 부분은 아무 작업도 수행하지 않지만 병합은 계속 실행됩니다. 따라서 현재 로컬 브랜치가 최신이 아닌 경우 새 변경 사항을 브랜치에 병합합니다. 그리고 빨리 감기 병합을 수행 할 수없는 경우 (다양한 커밋이있는 경우) 병합 커밋을 생성합니다.
찌르기

28
이 대답은 OP가 위험하다고 설명한 것처럼 rebase를 사용하는 것처럼 보이지만 그렇지 않습니다. 3 단계에서 리베이스는 전체 히스토리를 다시 작성하지 않습니다. 푸시되지 않은 로컬 커밋 만 새 HEAD (해당 분기에 푸시 된 최신 커밋) 위에 다시 적용되어 다시 작성됩니다. 이것은 불필요한 병합 커밋을 방지하고 다른 부작용이 없습니다.
bob esponja 2014

1
@bobesponja 풀링 된 원격 브랜치에없는 모든 커밋이 다시 작성됩니다. 여기에는 다른 분기에서 게시 된 커밋이 포함될 수 있습니다. 예를 들어 다른 분기가 이전에 이미 액세스했을 수있는 기능 분기가 포함됩니다. 그렇기 때문에 리베이스하는 것에 대해 생각하지 않고 리베이스하는 것은 다소 위험합니다.
poke a

1
@bobesponja 예, 기능 브랜치를 일찍 게시하는 경우 (다른 사람이 작업하거나 단순히 백업으로 작업하기 때문), 다른 사람이 이미 가져 왔을 수 있으므로 리베이스하지 않아야합니다. Rebasing은-당신이 스스로 말했듯이-내가 내 대답에 언급 한 지침을 rebasing하는 것입니다. 그러나 커밋을 게시하지 않으면 원하는 경우 리베이스하는 것이 좋으며 선형 기록을 신경 쓰지 마십시오. 그러나 그것은 당신이 일하는 방식에 따라 다르므로 일반적으로 안전하지 않으면 피하는 것입니다. Btw. 내 답변을 수정 했으므로 문제가 해결되면 반대표를 제거 해주시면 감사하겠습니다.
찌르기

48

이 답변은 나의 이해, 다이어그램 및 결론이 잘못되어 수정되었습니다.


git pullgit이 병합되기 때문에 병합 커밋이 발생합니다. 병합 대신 리베이스를 사용하도록 분기를 설정하여 변경할 수 있습니다. 풀에서 병합하는 대신 rebase를 사용하면 공유 저장소에 더 선형적인 기록이 제공됩니다. 반면에 병합 커밋은 브랜치에서의 병렬 개발 노력을 보여줍니다.

예를 들어 두 사람이 같은 지점에서 일하고 있습니다. 분기는 다음과 같이 시작합니다.

...->C1

첫 번째 사람이 작업을 마치고 지점으로 이동합니다.

...->C1->C2

두 번째 사람이 작업을 마치고 푸시를 원하지만 업데이트가 필요하기 때문에 할 수 없습니다. 두 번째 사람의 로컬 저장소는 다음과 같습니다.

...->C1->C3

풀이 병합으로 설정되면 두 번째 사람 저장소는 다음과 같습니다.

...->C1->C3->M1
      \      /
       ->C2->

M1은 병합 커밋입니다. 이 새로운 브랜치 기록은 리포지토리로 푸시됩니다. 대신 풀이 로컬 리포지토리를 리베이스하도록 설정되면 다음과 같습니다.

...->C1->C2->C3

병합 커밋이 없습니다. 역사는 더 선형 적으로 만들어졌습니다.

두 가지 선택 모두 지점의 역사를 반영합니다. git을 사용하면 선호하는 히스토리를 선택할 수 있습니다.

실제로 rebase가 원격 브랜치에 문제를 일으킬 수있는 곳이 있습니다. 이것은 그러한 경우 중 하나가 아닙니다. 우리는 이미 복잡한 브랜치 히스토리를 단순화하고 공유 저장소와 관련된 히스토리 버전을 보여주기 때문에 리베이스를 사용하는 것을 선호합니다.

branch.autosetuprebase = always를 설정하여 git이 자동으로 원격 분기를 master 대신 rebase로 설정하도록 할 수 있습니다.

git config --global branch.autosetuprebase always

이 설정은 git이 각 원격 분기에 대한 구성 설정을 자동으로 생성하도록합니다.

branch.<branchname>.rebase=true

이미 설정된 원격 브랜치에 대해 직접 설정할 수 있습니다.

git config branch.<branchname>.rebase true

이전 진술에 대해 질문하고 추구해 주신 @LaurensHolst에게 감사드립니다. 나는 확실히 git이 pull and merge 커밋과 함께 작동하는 방법에 대해 더 많이 배웠다.

병합 커밋에 대한 자세한 내용은 ProGit-Book 의 프로젝트기여를 참조하세요 . 개인 작은 팀 섹션 쇼 커밋을 병합합니다.


7
“풀에서 병합하는 대신 rebase를 사용하면 공유 저장소에 올바른 기록이 제공됩니다. 병합을 사용하면 잘못된 기록이 제공됩니다.” —이 대담한 진술을 뒷받침하는 근거는 무엇입니까? 병합 된 역사가 '거짓 역사'일 리는 없습니다. 일이 발생한 순서를 정확하게 묘사 한 것입니다. 리베이스로 수행하는 것은 실제로 역사를 변경 하여 약간 더 선형적인 버전을 만드는 것입니다. 미학을 위해 정확성을 희생합니다. 당신이 선호하는 일일 수도 있지만 더 진실 된 것은 아닙니다.
Laurens Holst

2
병합 대신 리베이스를 사용하면 미학의 정확성이 저하되지 않습니다. 병합에 --no-ff를 사용하므로 미학은 요구 사항이 아닙니다. 정확성은 욕망입니다. Rebase는 그 정확성을 제공합니다.
Bill Door

2
리베이스 히스토리는 어떻게 더 정확합니까? 당신은 이것을 명확히하지 않고 어떻게 될지 모르겠습니다.
Laurens Holst

1
기록은 공유 저장소 에서 커밋이 발생한 시간을 반영합니다 . 어느 날 공유 저장소는 커밋 C2를 보았습니다. 2 일차에 공유 리포지토리는 커밋 C3을 확인합니다. C3가 C2보다 먼저 나오면 시간의 반영이 정확하지 않습니다. C3은 C2보다 먼저 오지 않았습니다. 리베이스가하는 일은 로컬 리포지토리 에서 커밋을 다시 구성 하여 공유 리포지토리에 표시된 기록을 올바르게 반영하는 것입니다.
Bill Door

6
귀하의 질문으로 인해 병합 커밋에 대한 나의 이해를 검토하게되었습니다. 내 다이어그램이 잘못되었습니다. 토론을 수정하고 있습니다. 내 결론도 잘못되었습니다. rebase 및 merge 기록은 똑같이 정확합니다. 자신의 선택을 할 수 있습니다.
Bill Door

11

넌 할 수있어:

git pull --rebase

그러나 이렇게하면 항상 공동 작업자 위에 변경 사항이 적용됩니다. 그러나 오염 된 병합 메시지는받지 않습니다.


9

실제로 이것에 대한 훨씬 더 간단한 대답이 있습니다. 개발자 B가 커밋하기 전에 끌어 오기만하면됩니다. 이렇게하면 원격 저장소의 커밋 기록과 병합하려고하는 로컬 커밋에서 로컬 저장소에 만든 기록으로 인해 발생하는 병합 커밋을 방지 할 수 있습니다. pull을 할 때 'changes will be overwrite'줄을 따라 무언가를 말하는 메시지를 받으면 두 사람이 같은 파일을 터치했음을 의미하므로 다음과 같이하십시오.

git stash
git pull
git stash pop

그런 다음 병합 충돌이 있으면 해결할 수 있습니다.


가장 성 가시고 걱정스러운 것은 정확히 병합 충돌입니다. 나는 오히려 그것을 피할
녹색

1
@Green 병합 충돌이 걱정된다면 git pull도 다르지 않습니다.
Zoso

당신이 stash전에 잊었을 때를 제외하고 pull. Ugh git은 내가 항상 내 게임의 최상위에 있어야한다고 요구합니다.
linuxNoob

git pull --rebase원격 변경 사항을 로컬 변경 사항보다 먼저 통합 해야합니다 .
vonbrand

7

git pull을 수행하면 "Merge branch"메시지가 삽입됩니다. git pull을 수행하여 원격 분기를 로컬 분기에 병합했습니다.

git pull을 수행하고 충돌이 발생하면 git 로그에 충돌을 해결 한 사용자가 보낸 것으로 충돌하는 파일에 대한 업데이트가 표시됩니다. 충돌을 수정 한 사람이 파일을 다시 커밋하기 때문이라고 생각합니다.

내가 아는 한 그것이 git이 작동하는 방식이며 그 주위에는 방법이 없습니다.

Rebasing은 git 히스토리를 날려 버릴 것이므로 언제 병합이 발생했는지 알 수 없습니다.

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