요약
기본적으로 git pull
코드 기록에 노이즈와 복잡성을 추가하는 병합 커밋을 만듭니다. 또한 pull
수신 변경으로 인해 변경 사항이 어떻게 영향을 받을지 쉽게 생각할 수 없습니다.
git pull
명령은 너무 오래 그것은 단지 빨리 감기 병합을 수행으로 안전합니다. 경우 git pull
에 구성된 경우에만 빨리 감기 병합을하고 빨리 감기 병합 할 수없는 경우, 다음 힘내 오류와 함께 종료됩니다. 이렇게하면 들어오는 커밋을 연구하고 이들이 커밋이 로컬 커밋에 어떤 영향을 줄지 생각하고 최상의 작업 과정 (병합, 리베이스, 재설정 등)을 결정할 수 있습니다.
Git 2.0 이상에서는 다음을 실행할 수 있습니다.
git config --global pull.ff only
기본 동작을 빨리 감기로 변경합니다. 1.6.6에서 1.9.x 사이의 Git 버전을 사용하면 입력 습관을 들여야합니다.
git pull --ff-only
그러나 모든 버전의 Git에서는 git up
다음과 같이 별칭을 구성하는 것이 좋습니다 .
git config --global alias.up '!git remote update -p; git merge --ff-only @{u}'
git up
대신에 사용 합니다 git pull
. 다음과 같은 이유로이 별칭을 선호합니다 git pull --ff-only
.
- Git의 모든 (고대가 아닌) 버전에서 작동합니다.
- 현재 진행중인 지점뿐만 아니라 모든 업스트림 지점을 가져옵니다.
origin/*
더 이상 업스트림에 존재하지 않는 오래된 가지를 정리합니다 .
문제 git pull
git pull
제대로 사용하면 나쁘지 않습니다. Git의 최근 몇 가지 변경 사항으로 git pull
올바르게 사용하기가 쉽지만 불행히도 평야의 기본 동작 git pull
에는 몇 가지 문제가 있습니다.
- 그것은 역사에서 불필요한 비선형 성을 소개합니다
- 의도적으로 업스트림 아웃백 된 커밋을 실수로 쉽게 다시 도입 할 수 있습니다.
- 예상치 못한 방식으로 작업 디렉토리를 수정합니다.
- 다른 사람의 작업을 검토하기 위해하고있는 일을 일시 중지하면
git pull
- 원격 브랜치에 올바르게 리베이스하기가 어렵습니다.
- 원격 저장소에서 삭제 된 분기를 정리하지 않습니다.
이러한 문제는 아래에 더 자세히 설명되어 있습니다.
비선형 역사
기본적 git pull
으로이 명령은 running git fetch
다음에 오는 것과 같습니다 git merge @{u}
. 로컬 리포지토리에 푸시되지 않은 커밋이 있으면 병합 부분이 git pull
병합 커밋 을 만듭니다.
병합 커밋에 대해 본질적으로 나쁜 것은 없지만 위험 할 수 있으므로 존중해야합니다.
- 병합 커밋은 본질적으로 검사하기가 어렵습니다. 합병이 무엇을하는지 이해하려면 모든 부모와의 차이점을 이해해야합니다. 기존의 차이점은이 다차원 정보를 잘 전달하지 못합니다. 반대로 일련의 일반 커밋은 검토하기 쉽습니다.
- 병합 충돌 해결은 까다 롭고 병합 커밋을 검토하기가 어렵 기 때문에 실수가 오랫동안 감지되지 않는 경우가 많습니다.
- 병합은 정기적 커밋의 영향을 조용히 대체 할 수 있습니다. 이 코드는 더 이상 증분 커밋의 합계가 아니므로 실제로 변경된 사항에 대한 오해가 발생합니다.
- 병합 커밋은 일부 지속적인 통합 체계를 방해 할 수 있습니다 (예 : 두 번째 부모가 진행중인 불완전한 작업을 가리키는 가정 된 규칙에 따라 첫 번째 부모 경로 만 자동 빌드).
물론 병합 할 시간과 장소가 있지만 병합을 사용하거나 사용하지 않아야 할시기를 이해하면 리포지토리의 유용성을 향상시킬 수 있습니다.
Git의 목적은 코드베이스의 진화를 쉽게 공유하고 소비 할 수 있도록하는 것이며, 전개 된대로 정확하게 기록을 기록하지는 않습니다. (동의하지 않는 경우 rebase
명령 및 생성 된 이유를 고려하십시오 .) 생성 된 병합 커밋은 git pull
유용한 의미를 다른 사람에게 전달하지 않습니다. 다른 사람이 변경 작업을 수행하기 전에 다른 사람이 저장소로 푸시했다고 말합니다. 다른 사람들에게 의미가없고 위험 할 수있는 커밋을 병합 한 이유는 무엇입니까?
git pull
병합 대신 리베이스 하도록 구성 할 수도 있지만 문제가 있습니다 (나중에 설명). 대신 git pull
빨리 감기 병합 만 수행하도록 구성해야합니다.
재 확보 된 커밋의 재 도입
누군가가 지점을 리베이스하고 강제로 밀고 있다고 가정하십시오. 이것은 일반적으로 발생하지 않아야하지만 때때로 필요합니다 (예 : 실수로 커밋되어 푸시 된 50GiB 로그 파일 제거). 병합을 수행 git pull
하면 업스트림 분기의 새 버전이 로컬 리포지토리에 여전히 존재하는 이전 버전으로 병합됩니다 . 결과를 누르면 피치 포크와 횃불이 나옵니다.
일부는 실제 문제가 강제 업데이트라고 주장 할 수 있습니다. 예, 일반적으로 가능할 때마다 강제 푸시를 피하는 것이 좋지만 때로는 피할 수없는 경우도 있습니다. 개발자는 때때로 업데이트되기 때문에 강제 업데이트를 처리 할 준비가되어 있어야합니다. 이것은 일반적인 커밋을 통해 이전 커밋에서 맹목적으로 병합하지 않음을 의미 git pull
합니다.
놀라운 작업 디렉토리 수정
작업 디렉토리 나 색인 git pull
이 완료 될 때까지 어떻게 보일지 예측할 방법이 없습니다 . 다른 작업을 수행하기 전에 해결해야 할 병합 충돌이있을 수 있습니다. 누군가 실수로 파일을 푸시했거나 작업중인 디렉토리의 이름을 바꿀 수 있기 때문에 작업 디렉토리에 50GiB 로그 파일이 나타날 수 있습니다.
git remote update -p
(또는 git fetch --all -p
)를 사용하면 병합 또는 리베이스를 결정하기 전에 다른 사람의 커밋을 살펴볼 수 있으므로 조치를 취하기 전에 계획을 수립 할 수 있습니다.
다른 사람의 커밋을 검토하기 어려움
당신이 약간의 변화를 겪고 있고 누군가 다른 사람들이 방금 밀었던 커밋을 검토하기를 원한다고 가정 해보십시오. git pull
의 병합 (또는 리베이스) 작업은 작업 디렉토리와 색인을 수정합니다. 즉, 작업 디렉토리와 색인이 깨끗해야합니다.
을 사용한 git stash
다음을 사용할 수 git pull
있지만 검토가 끝나면 어떻게합니까? 원래 위치로 돌아가려면 만든 병합을 실행 취소 git pull
하고 숨김을 적용해야합니다.
git remote update -p
(또는 git fetch --all -p
)는 작업 디렉토리 또는 색인을 수정하지 않으므로 단계적 및 / 또는 단계적 변경 사항이 없더라도 언제든지 실행하는 것이 안전합니다. 작업중인 작업을 일시 중지하고 작업중인 커밋을 정리하거나 마무리하지 않아도 다른 사람의 커밋을 검토 할 수 있습니다. git pull
유연성을 제공하지 않습니다.
원격 지점에 기초
일반적인 Git 사용 패턴은 도입 된 병합 커밋을 제거하기 위해 git pull
최신 변경 사항을 가져온 다음에 a git rebase @{u}
를 수행하는 것입니다 git pull
. 이 망할 놈의 말에 의해 하나의 단계로이 두 단계를 줄이기 위해 일부 구성 옵션을 가지고 일반적인 충분 git pull
대신 병합의 REBASE을 수행 할을합니다 (참조 branch.<branch>.rebase
, branch.autosetuprebase
및 pull.rebase
옵션).
불행하게도, 유지하려는 푸시 master
되지 않은 병합 커밋이있는 경우 (예 : 푸시 된 기능 분기를에 병합하는 커밋 ) rebase-pull ( git pull
로 branch.<branch>.rebase
설정 됨 true
)이나 merge-pull (기본 git pull
동작) 다음에 rebase가 작동합니다. 옵션 git rebase
없이 병합을 제거 하기 때문입니다 (DAG를 선형화 함) --preserve-merges
. rebase-pull 작업은 병합을 유지하도록 구성 할 수 없으며 merge-pull 다음에 오는 것은 merge-pull로 git rebase -p @{u}
인한 병합을 제거하지 않습니다. 업데이트 : 힘내 v1.8.5 추가 git pull --rebase=preserve
하고 git config pull.rebase preserve
. 이것은 업스트림 커밋을 가져온 후 git pull
수행 git rebase --preserve-merges
됩니다. ( 헤드 업을위한 funkaster 에 감사 합니다!)
삭제 된 분기 정리
git pull
원격 저장소에서 삭제 된 분기에 해당하는 원격 추적 분기를 제거하지 않습니다. 예를 들어, 누군가 foo
원격 리포지토리에서 분기 를 삭제해도 여전히 표시 origin/foo
됩니다.
이로 인해 사용자는 죽인 지점이 여전히 활성 상태라고 생각하기 때문에 실수로 부활하게됩니다.
더 나은 대안 : git up
대신 사용git pull
대신 git pull
다음 git up
별칭을 만들어 사용하는 것이 좋습니다 .
git config --global alias.up '!git remote update -p; git merge --ff-only @{u}'
이 별명은 모든 업스트림 브랜치에서 모든 최신 커밋을 다운로드하고 (불량 브랜치 정리) 로컬 브랜치를 업스트림 브랜치의 최신 커밋으로 빨리 전달하려고합니다. 성공하면 로컬 커밋이 없으므로 병합 충돌의 위험이 없습니다. 로컬 (푸시되지 않은) 커밋이 있으면 빨리 감기에 실패하여 작업을 수행하기 전에 업스트림 커밋을 검토 할 수 있습니다.
이것은 여전히 예측할 수없는 방식으로 작업 디렉토리를 수정하지만 로컬 변경이없는 경우에만 가능합니다. 달리 git pull
, git up
당신이 병합 충돌을 해결하기 위해 기대 프롬프트로 드롭하지 않습니다.
다른 옵션 : git pull --ff-only --all -p
다음은 위의 git up
별명에 대한 대안입니다 .
git config --global alias.up 'pull --ff-only --all -p'
이 버전 git up
은 다음을 git up
제외하고 이전 별명 과 동일한 동작을합니다 .
- 로컬 브랜치가 업스트림 브랜치로 구성되지 않은 경우 오류 메시지가 조금 더 복잡합니다.
- 향후 버전의 Git에서 변경 될 수 있는 문서화되지 않은 기능 (에
-p
전달 된 인수) 에 의존합니다.fetch
Git 2.0 이상을 실행중인 경우
Git 2.0 이상 git pull
에서는 기본적으로 빨리 감기 만 수행 하도록 구성 할 수 있습니다 .
git config --global pull.ff only
이처럼 git pull
작동 git pull --ff-only
하지만 여전히 모든 업스트림 커밋을 가져 오거나 이전 origin/*
분기를 정리하지 않으므로 여전히 선호합니다 git up
.