원격 Git 저장소에서 특정 커밋 검색


189

내 PC에서 복제하지 않고 원격 Git 저장소에서 특정 커밋을 하나만 검색하는 방법이 있습니까? 원격 저장소의 구조는 내 구조와 완전히 동일하므로 충돌이 발생하지 않지만 어떻게 해야할지 모르겠으며 거대한 저장소를 복제하고 싶지 않습니다.

나는 자식을 처음 사용하는데 어떤 방법이 있습니까?


1
기존 저장소가 이미 원격 저장소의 복제본입니까, 아니면 완전히 다른가요?
CharlesB

레포는 리눅스 커널 소스이며, 거의 동일합니다
Varun Chitre

복제품입니까 아니면 아니오입니까?
CharlesB

1
정확히. 이것을 고려하십시오. 원격 저장소가 헤드 D에 있고 광산이 헤드 A에 있고 B, C, D 커밋 뒤에 있습니다. 이 리포지토리의 B, C, D 커밋이 자신의 전문 분야와 다르기 때문에 한 리포지토리의 커밋 B와 다른 리포지토리의 C와 다른 하나의 D를 병합하고 싶습니다.
Varun Chitre

1
@VarunChitre VonC의 다른 답변을 받아 들일 수 있습니까?
CharlesB

답변:


109

Git 버전 2.5 이상 (Q2 2015)부터는 전체 커밋을 복제하지 않고 단일 커밋을 가져 오는 것이 실제로 가능합니다.

참조 68ee628을 투입 하여 프레드릭 메들리 ( moroten) 5 월 21 일 2015 년
(에 의해 합병 Junio C 하마노 - gitster-a9d3493 커밋 2015 6월 1일)

이제 서버 측에 새로운 구성이 있습니다.

uploadpack.allowReachableSHA1InWant

upload-pack참조 팁에서 도달 할 수있는 객체를 요청하는 가져 오기 요청을 허용 합니다. 그러나 객체 도달 가능성을 계산하는 것은 계산 비용이 많이 듭니다.
기본값은 false입니다.

해당 서버 측 구성을 단순 복제본 ( git fetch --depth=1) 과 결합 하면 단일 커밋을 요청할 수 있습니다 (참조 t/t5516-fetch-push.sh:

git fetch --depth=1 ../testrepo/.git $SHA1

git cat-file명령을 사용하여 커밋이 페치되었음을 확인할 수 있습니다 .

git cat-file commit $SHA1

" git upload-pack"를 제공하는 " git fetch"는 uploadpack.allowReachableSHA1InWant 구성 변수 를 사용하여 참조에서 도달 할 수있는 한 참조의 끝에없는 커밋을 제공하도록 지시 할 수 있습니다 .


전체 문서는 다음과 같습니다.

upload-pack: 선택적으로 도달 가능한 sha1 가져 오기 허용

uploadpack.allowReachableSHA1InWant서버 측에 구성 옵션이 설정되어 있으면 " git fetch"는 광고되지 않은 오브젝트의 이름을 지정하는 "want"행을 사용하여 요청할 수 있습니다 (대역 외부 또는 서브 모듈 포인터에서 얻은 것 같습니다).
분기 팁에서 도달 할 수있는 개체, 즉에 의해 광고 된 분기와 분기의 합집합 transfer.hideRefs만 처리됩니다.
연결 가능성을 확인하기 위해 기록을 다시 걸어야하는 관련 비용이 있습니다.

이 기능은 특히 얕은 가져 오기가 사용되는 경우 전체 저장소를 복제 할 필요없이 sha1이 알려진 특정 커밋의 컨텐츠를 가져올 때 사용할 수 있습니다.

유용한 사례는 예를 들어

  • 히스토리에 큰 파일이 포함 된 저장소
  • 서브 모듈 체크 아웃에 필요한 데이터 만 가져 오기
  • 변경 번호 대신 커밋의 관점에서 생각하는 경우 Ger1에 속한 정확한 지점을 알려주지 않고 sha1을 공유 할 때.
    (Gerrit 사례는 allowTipSHA1InWant모든 Gerrit 변경이 참조 할 때 이미 해결되었습니다 .)

Git 2.6 (2015 년 3 분기)은이 모델을 개선 할 것입니다. Jeff King ( )의 commit 2bc31d1 , commit cc118a6 (2015 년 7 월 28 일)을
참조하십시오 . ( Junio ​​C Hamano의해 합병 -- 커밋 824a0be , 2015 년 8 월 19 일)peff
gitster

refs: 부정적인 지원 transfer.hideRefs

transfer.hideRefs구성을 사용하여 참조의 계층 구조를 숨기면 나중에 해당 구성을 재정 의하여 "숨기기 해제"할 수 없습니다.
이 패치는 "부정적인"숨기기를 구현하여 다른 일치하는 것이 숨겨져 있어도 일치하지 않는 것으로 표시됩니다.
우리는 구성 기계 장치가 우리에게 공급하는 방식에서 역순으로 경기를 역순으로 적용하는데, 이는 우리의 일반적인 "마지막 승리"구성 우선 순위 작업을 가능하게합니다 ( .git/config예를 들어,의 항목 은 재정의 함 /etc/gitconfig).

이제 할 수 있습니다 :

git config --system transfer.hideRefs refs/secret
git config transfer.hideRefs '!refs/secret/not-so-secret'

refs/secret특정 리포지토리에서 하나의 퍼블릭 비트를 제외하고 모든 리포지토리에서 숨길 수 있습니다.


힘내 2.7 (2015 년 11 월 / 12 월)이 다시 개선됩니다 :

참조 948bfa2 커밋 , 00b293e 커밋 (2015 11월 5일를) 78a766a 커밋 , 92cab49 커밋 , 92cab49 커밋 , 92cab49 커밋 (2015 11월 3일), 00b293e 커밋 , 00b293e 커밋 (2015 11월 5일을), 및 92cab49 커밋 , 92cab49 커밋 , 92cab49 커밋 , Lukas Fleischer ( )의 커밋 92cab49 (2015 년 11 월 3 일 ) . 도움 : Eric Sunshine ( ) . (가 합병 제프 킹 - -dbba85e 커밋 , 2015년 11월 20일)lfos
sunshineco
peff

config.txt: hideRefs네임 스페이스로 의미를 문서화

현재 transfer.hideRefs네임 스페이스가 설정 될 때 어떻게 동작해야하는지 에 대한 명확한 정의는 없습니다 . 이 경우 접두사가 제거 된 이름과 일치
한다고 설명하십시오 hideRefs. hideRefs수신 팩에서 현재 패턴을 처리 하는 방법 입니다.

hideRefs : 전체 심판 일치 지원 추가

벗겨진 참조를 일치시키는 것 외에도 이제 hideRefs전체 ( 스트립되지 않은) 참조가 일치하는 패턴을 추가 할 수 있습니다 .
제거 된 일치 항목과 완전 일치 항목을 구분하려면 이러한 새 패턴 앞에 접곡 부호 ( ^)를 붙여야합니다 .

따라서 새로운 문서 :

transfer.hideRefs:

네임 스페이스가 사용중인 경우 네임 스페이스 접두사는 transfer.hiderefs패턴 과 일치하기 전에 각 참조에서 제거됩니다 .
예를 들어,이 refs/heads/master에 지정되어 transfer.hideRefs현재 네임 스페이스가되어 foo, 다음 refs/namespaces/foo/refs/heads/master 광고들에서 생략되어 있지만 refs/heads/masterrefs/namespaces/bar/refs/heads/master여전히 소위 "이"선으로 광고됩니다.
벗기기 전에 심판을 일치 ^시키려면 심판 이름 앞에를 추가하십시오 . 당신이 결합하는 경우 !^, !먼저 지정해야합니다.


R .. 은 주석 에서 config를 언급 하며uploadpack.allowAnySHA1InWant , 이는 객체를 요청 upload-pack하는 fetch요청 을 받아 들일 수 있습니다 . (기본값은 false)입니다.

David "novalis"Turner ( )의 커밋 f8edeaa (2016 년 11 월, Git v2.11.1)를 참조하십시오 .novalis

upload-pack: 선택적으로 sha1 가져 오기 허용

우리가 사용자가 저장소의 모든 것에 절대적으로 액세스 할 것을 신뢰하는 경우 도달 가능성 검사를하는 것은 약간 어리석은 것처럼 보입니다.

또한 분산 시스템에서는 비참합니다. 어쩌면 한 서버는 심판을 광고하지만 다른 서버는 그 심판에 강제로 밀렸으며 두 HTTP 요청은 이러한 다른 서버로 향하게됩니다.


4
이 단일 커밋만으로 repo 클론을 생성하는 방법에 대한보다 완전한 예를 들어 줄 수 있습니까? 시도했지만 실패했습니다. 감사합니다!
Lars Bilke

1
GitHub로 푸시하고 싶습니다. 어쩌면 그들은 이것을 허용하지 않을 수도 있습니다.
Lars Bilke

2
@LarsBilke 우리는 복제에 대해 이야기하거나 푸시하지 않습니다. 그리고 나는 GitHub이 아직 서버 측에 Git 2.5를 가지고 있지 않다고 확신합니다.
VonC

2
더 좋은 점 uploadpack.allowAnySHA1InWant은 도달 가능성 계산 페널티 (및 DoS 벡터)가없는 것입니다.
R .. GitHub 중지 지원 얼음

1
감사! 나는 그들이 "공개하지 않으려는 무작위 쓰레기를 밀어 내지 말고 repo 저자를 신뢰하는 것"보다는 "사용자가 액세스 할 수 있도록 믿으십시오"라고 설명하는 것이 재미 있다고 생각합니다.
R .. GitHub 중지 지원 얼음

98

한 번만 복제하므로 이미 원격 저장소의 복제본이있는 경우 복제하면 모든 항목이 다시 다운로드되지 않습니다. 가져 오려는 분기를 표시하거나 변경 사항을 가져오고 원하는 커밋을 체크 아웃하십시오.

새로운 저장소에서 가져 오는 것은 대역폭 이 매우 저렴합니다. 변경 사항이없는 경우에만 다운로드하기 때문입니다. 최소한의 부하로 Git이 올바른 일을한다고 생각하십시오.

Git은 모든 것을 .git폴더에 저장 합니다. 커밋은 가져 와서 분리하여 저장할 수 없으며 모든 조상이 필요합니다. 그들은 서로 관련되어 있습니다.


그러나 다운로드 크기를 줄이려면 git에게 특정 브랜치 또는 커밋과 관련된 객체 만 가져 오도록 요청할 수 있습니다.

git fetch origin refs/heads/branch:refs/remotes/origin/branch

이것은 원격 브랜치 branch (그리고 당신이 놓친 것)에 포함 된 커밋 만 다운로드 하여 저장합니다 origin/branch. 그런 다음 병합 또는 체크 아웃 할 수 있습니다.

SHA1 커밋 만 지정할 수도 있습니다.

git fetch origin 96de5297df870:refs/remotes/origin/foo-commit

이것은 지정된 SHA-1 96de5297df870 (그리고 당신이 놓친 조상)의 커밋 만 다운로드하고 (존재하지 않는) 원격 브랜치로 저장합니다 origin/foo-commit.


3
클론이 무엇을 의미하는지 혼동하는 것 같습니다. 원격 저장소에서 변경 사항을 가져올 때 복제하지 않고 기록에서 커밋을 가져옵니다. 그런 다음 체크 아웃 할 커밋을 선택하거나 내역에 병합합니다
CharlesB

1
여전히 git fetch로 많은 데이터 (430mb)를 다운로드합니다. 필요한 커밋은 몇 KB에 불과합니다. 이 작업을 실제로 수행 할 특별한 명령이 없습니까? 그리고 'git fetched'저장소를 제거하려면 어떻게해야합니까? 어디에 저장되어 있습니까?
Varun Chitre 2013

9
지금은 구식입니다. 우리는 얕은 복제 를 수행 하고 단일 커밋가져올 수있는 기능을 가지고 있습니다 . 얕은 클론은 이제 프로젝트의 전체 히스토리를 알 필요없이 정상적으로 푸시 및 페치 할 수 있으므로 커밋이 조상없이 단독으로 존재할 수 없다고 말하는 것은 더 이상 올바르지 않습니다. 초기 복제 후 가져 오기에 대해 말하는 것은 매우 사실이지만 더 저렴한 옵션도 있습니다.
Theodore Murdock

6
마지막 명령 (SHA1 커밋 사용)이 작동하지 않습니다. 이 명령은 잠시 동안 "무언가"를 수행 한 다음 메시지 나 명백한 부작용없이 종료됩니다.
HRJ

1
@ HRJ 예, 우분투 16.04에서 Git과 함께이 문제가 발생했습니다 2.7.4-0ubuntu1.3. 그러나 2.16.2-0ppa1~ubuntu16.04.1git-core PPA에서 사용할 때는 정상적으로 작동합니다. 수정 된 버그처럼 들립니다. 빠른 검색으로 참조를 찾을 수 없습니다. 누군가 나에게 그에 대한 포인터를 얻을 수 있다면이 수정 프로그램을 백 포트하도록하고 싶습니다.
gertvdijk

62

git repo를 가져 왔습니다.

git pull --rebase <repo> <branch>

git이 브랜치의 모든 코드를 가져 오도록 허용 한 다음 관심있는 커밋으로 재설정했습니다.

git reset --hard <commit-hash>

도움이 되었기를 바랍니다.


1
이 답변은 효과가 없었지만 내 생명을 구했습니다! 무리 감사!
michaeltintiuc

재설정-하드 복제 후 나를 위해 일했다! 감사.
Nick-ACNB

3
-1 : git reset --hard일반화 된 솔루션에서 공유 할 때 와 같은 "파괴적인"명령은 사람들이 데이터를 잃어버린 곳 (또는이 경우 : 데이터를 되 찾는 것이 중요하지 않은 상태)에 빠질 수 있습니다.
yaauie

54

당신은 단순히 원격 저장소의 단일 커밋을 가져올 수 있습니다

git fetch <repo> <commit>

어디,

  • <repo>원격 REPO 이름 (예, 할 수 있습니다 origin(예를) 또는 원격의 repo URL을 https://git.foo.com/myrepo.git)
  • <commit> SHA1 커밋이 될 수 있습니다

예를 들어

git fetch https://git.foo.com/myrepo.git 0a071603d87e0b89738599c160583a19a6d95545

커밋 (및 누락 된 조상)을 가져온 후에는 간단히 커밋을 할 수 있습니다

git checkout FETCH_HEAD

이렇게하면 "분리 된 헤드"상태가됩니다.


10
내가 fetch당신처럼 특정 rev를 시도하면 git이 오류 코드 1로 실패하고 출력이 없습니다. 이것은 과거 버전에서 작동했던 것이 었습니까? (나는 v2.0.2입니다.)
Jack O'Connor

2
편집 : 이미 전체 커밋을 수행 한 것처럼 로컬에 해당 커밋이 있으면 작동합니다.이 fetch경우 사용법이 확실하지 않습니다.
Jack O'Connor 16 :

2
실제로 이것은 git 2.0.2에서도 더 이상 작동하지 않는 것 같습니다. :(
흐름

2
git checkout FETCH_HEAD도움이됩니다.
lzl124631x

1
이 방법은 얕은 가져 오기 (예 :)에서는 작동하지 않습니다 --depth=1!
kingmakerking

16

다음과 같이 간단히 원격 저장소를 가져올 수 있습니다.

git fetch <repo>

어디,

  • <repo>원격 REPO 이름 (예, 할 수 있습니다 origin(예를) 또는 원격의 repo URL을 https://git.foo.com/myrepo.git)

예를 들면 다음과 같습니다.

git fetch https://git.foo.com/myrepo.git 

repos를 가져온 후 원하는 커밋을 병합 할 수 있습니다 (질문은 하나의 커밋을 검색하는 것이기 때문에 병합 대신 cherry-pick을 사용하여 하나의 커밋을 선택할 수 있습니다).

git merge <commit>
  • <commit> SHA1 커밋이 될 수 있습니다

예를 들면 다음과 같습니다.

git cherry-pick 0a071603d87e0b89738599c160583a19a6d95545

또는

git merge 0a071603d87e0b89738599c160583a19a6d95545

병합하려는 최신 커밋 인 경우 FETCH_HEAD 변수를 사용할 수도 있습니다.

git cherry-pick (or merge) FETCH_HEAD

머신에서 Git 계정 설정이 필요합니다. 테스트 계정에서는 작동하지 않습니다. 테스트 계정으로 작동하는 것이 있습니까?
jww

무슨 뜻이야? git fetch를 할 수 없습니까?
Sérgio

명령은 git config set uploadpack.allowReachableSHA1InWant ?
Alexander Mills

2

이것은 가장 잘 작동합니다 :

git fetch origin specific_commit
git checkout -b temp FETCH_HEAD

원하는 이름을 "temp"로 지정합니다.이 분기는 분리 될 수 있습니다.


분명하지 오래된 자식 버전에 1.8.x 등으로
소린

1

마지막으로 git cherry-pick을 사용하여 특정 커밋을 복제하는 방법을 찾았 습니다 . 로컬에 리포지토리가 없으며 원격에서 특정 커밋을 가져오고 있다고 가정하면,

1) 로컬 및 git init 에 빈 저장소를 만듭니다.

2) git remote add origin " url-of-repository "

3) git fetch origin [이것은 병합하지 않으면 파일을 로컬 작업 공간으로 이동시키지 않습니다]

4) git cherry-pick " Enter-long-commit-hash-that-you- 필요한 "

이렇게하면 로컬에 해당 커밋의 파일 만 있습니다.

긴 커밋 해시 입력 :

이것을 사용하여 얻을 수 있습니다-> git log --pretty = oneline



0

요청 된 커밋이 원격 리포지토리의 풀 요청에있는 경우 ID로 가져올 수 있습니다.

# Add the remote repo path, let's call it 'upstream':
git remote add upstream https://github.com/repo/project.git

# checkout the pull ID, for example ID '60':
git fetch upstream pull/60/head && git checkout FETCH_HEAD
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.