얕은 자식 서브 모듈을 만드는 방법?
얕은 서브 모듈을 가질 수 있습니까? 나는 각각 긴 역사를 가진 여러 개의 서브 모듈을 가진 수퍼 프로젝트를 가지고 있기 때문에 모든 역사를 불필요하게 끌고 있습니다.
내가 찾은 것은 이 답변되지 않은 스레드 입니다.
이것을 구현하기 위해 git-submodule 을 해킹 해야합니까 ?
다가오는 git1.8.4 의 새로운 기능 (2013 년 7 월) :
"
git submodule update
"는 선택적으로 서브 모듈 저장소를 얕게 복제 할 수 있습니다.
(그리고 git 2.10 Q3 2016에서는이를 기록 할 수 있습니다 git config -f .gitmodules submodule.<name>.shallow true
.
이 답변의 끝을 참조하십시오)
commit 275cd184d52b5b81cb89e4ec33e540fb2ae61c1f를 참조하십시오 .
추가
--depth
한 다음 복제 명령에 전달한다 "자식 서브 모듈"의 추가 및 업데이트 명령에 옵션을 선택합니다. 이것은 서브 모듈이 크며 최근 커밋에 관심이없는 경우에 유용합니다.테스트가 추가되고 "서브 모듈 업데이트는 pwd에서 심볼릭 링크를 처리 할 수 있습니다"의 나머지 테스트 파일에 맞게 일부 들여 쓰기 조정이 이루어졌습니다.
서명자 : Fredrik Gustafsson
<iveqy@iveqy.com>
Acked-by : Jens Lehmann<Jens.Lehmann@web.de>
이것은 이것이 작동한다는 것을 의미합니다.
git submodule add --depth 1 -- repository path
git submodule update --depth -- [<path>...]
와:
--depth::
이 옵션은
add
및update
명령에 유효 합니다.
지정된 수의 개정판으로 기록이 잘린 '얕은'복제본을 만듭니다.
내가 알 수있는 한이 옵션은
master
매우 밀접하게 추적되지 않는 하위 모듈에는 사용할 수 없습니다 . 깊이 1을 설정submodule update
하면 원하는 서브 모듈 커밋이 최신 마스터 인 경우에만 성공할 수 있습니다. 그렇지 않으면 "fatal: reference is not a tree
"가 나타납니다 .
사실입니다.
즉, git 2.8 (2016 년 3 월)까지. 2.8을 사용하면 submodule update --depth
SHA1에 원격 저장소 HEAD 중 하나에서 직접 연결할 수 있어도 성공할 수있는 기회가 한 번 더 있습니다.
Stefan Beller ( )의 commit fb43e31 (2016 년 2 월 24 일)을 참조하십시오 . 도움 : Junio C Hamano ( ) . (의해 병합 - Junio C 하마노 - 에 9671a76 커밋 2,016 26 이월)stefanbeller
gitster
gitster
하위 모듈 : sha1을 직접 가져 와서 필요한 sha1을 가져 오려고 더 열심히 시도
Gerrit에서 하위 모듈도 업데이트하는 변경 사항을 검토 할 때 일반적인 검토 방법은 패치를 로컬로 다운로드하여 선택하여 테스트하는 것입니다.
그러나 로컬에서 테스트 할 때git submodule update
서브 모듈의 해당 커밋이 아직 프로젝트 히스토리의 일부가 아니고 제안 된 변경 사항이므로 ' '이 (가) 올바른 서브 모듈 sha1을 가져 오지 못할 수 있습니다.
$sha1
기본 페치의 일부가 아닌 경우$sha1
직접 페치를 시도합니다 . 그러나 일부 서버는 sha1에 의한 직접 가져 오기를 지원하지 않아git-fetch
빠르게 실패합니다.
여전히 누락 된 sha1이 체크 아웃 단계에서 나중에 실패로 이어 지므로 여기서 실패 할 수 있으므로 여기서 실패하면 얻을 수 있습니다.
MVG는 fb43e31 (git 2.9, 2016 년 2 월) 을 커밋하겠다는 의견 을 지적했다
나에게 보일 수있을 것입니다 fb43e31 커밋 요청을하여, 그래서 SHA1의 ID로 커밋없는
uploadpack.allowReachableSHA1InWant
및uploadpack.allowTipSHA1InWant
서버의 설정은 아마이 작품의 여부에 영향을 미칠 것입니다.
나는 오늘 자식 목록에 게시물을 작성하여 얕은 서브 모듈을 사용하여 일부 시나리오, 즉 커밋도 태그 인 경우 어떻게 더 잘 작동 할 수 있는지 지적했다.
기다리고 보자.이것이 fb43e31이 특정 SHA1에 대한 페치를 기본 분기에 대한 페치 후에 폴백으로 만든 이유라고 생각합니다.
그럼에도 불구하고“--depth 1”의 경우 조기에 중단하는 것이 합리적이라고 생각합니다. 나열된 ref가 요청 된 ref와 일치하지 않고 SHA1의 요청이 서버에서 지원되지 않으면 아무런 의미가 없습니다. 하위 모듈 요구 사항을 어느 쪽이든 만족시킬 수 없으므로 아무것도 가져 오지 않습니다.
2016 년 8 월 업데이트 (3 년 후)
Git 2.10 (2016 년 3 분기)을 사용하면
git config -f .gitmodules submodule.<name>.shallow true
자세한 내용은 " 추가 무게가없는 Git 서브 모듈 "을 참조하십시오.
Git 2.13 (2017 년 2 분기 )은 Sebastian Schuberth ( )의 커밋 8d3047c (2017 년 4 월 19 일 )를 추가 합니다. (의해 병합 세바스찬 SCHUBERTH - - 에 8d3047c 커밋 20 사월 2017)sschuberth
sschuberth
이 서브 모듈의 복제는 얕은 복제 (역사 깊이가 1) 로 수행됩니다.
그러나 Ciro Santilli 는 주석 (및 그의 답변에 대한 세부 사항 )을 추가합니다
shallow = true
에.gitmodules
단지가 영향을 사용할 때 참조는 원격의 HEAD에 의해 추적--recurse-submodules
대상이 브랜치가 가리키는 커밋하더라도, 당신은 넣어 경우에도branch = mybranch
온.gitmodules
뿐만 아니라.
Git 2.20 (Q4 2018)은 작업 트리에서 파일이 누락 HEAD:.gitmodules
될 때 Blob에서 읽도록 업데이트 된 서브 모듈 지원을 개선합니다 .gitmodules
.
참조 2b1257e 커밋 , 76e9bdc 커밋 (2018년 10월 25일), 및 b5c259f 커밋 , 23dd8f5 커밋 , b2faad4 커밋 , 2502ffc 커밋 , 996df4d 커밋 , d1b13df 커밋 , 45f5ef3 커밋 , bcbc780 커밋 에 의해 (2018년 10월 5일) 안토니오 Ospite을 ( ao2
) .
(의해 병합 - Junio C 하마노 gitster
- 에 abb4824 커밋 2,018 13 년 11)
submodule
:.gitmodules
작업 트리에 없을 때 읽기 지원때
.gitmodules
파일이 작업 트리에 사용할 수없는 인덱스에서 현재 지점에서 콘텐츠를 사용해보십시오.
파일이 리포지토리의 일부이지만 어떤 이유로 파일이 체크 아웃되지 않은 경우 (예 : 스파 스 체크 아웃)가 여기에 해당합니다.이로써 적어도 사용하게 '
git submodule
'명령을 읽어gitmodules
완전히 작업 트리를 채우지 않고 구성 파일을.에 쓰려면
.gitmodules
여전히 파일을 체크 아웃해야하므로을 호출하기 전에 파일을 확인하십시오config_set_in_gitmodules_file_gently
.안전하게 쓸 수 없을 때
git-submodule.sh::cmd_add()
"git submodule add
"명령 의 결과적인 실패를 예상하기 위해 비슷한 검사를 추가하십시오.gitmodules
. 이것은 명령이 저장소를 가짜 상태로 두는 것을 방지합니다 (예 : 서브 모듈 저장소가 복제되었지만 실패로.gitmodules
인해 업데이트되지config_set_in_gitmodules_file_gently
않았습니다).또한
config_from_gitmodules()
이제 전역 객체 저장소에 액세스하므로 전역 객체 저장소에 대한 동시 액세스로부터 함수를 호출하는 모든 코드 경로를 보호해야합니다.
현재는이 경우에만 발생builtin/grep.c::grep_submodules()
하므로grep_read_lock()
관련된 코드를 호출 하기 전에 호출하십시오config_from_gitmodules()
.참고 :이 새로운 기능이 아직 제대로 작동하지 않는 드문 경우가
.gitmodules
있습니다. 작업 트리에 없는 중첩 된 하위 모듈 .
Git 2.9.0 은 하위 모듈 얕은 복제를 직접 지원하므로 이제 다음을 호출 할 수 있습니다.
git clone url://to/source/repository --recursive --shallow-submodules
Ryan의 대답에 따라 모든 하위 모듈을 반복하고 얕은 복제를 수행하는이 간단한 스크립트를 만들 수있었습니다.
#!/bin/bash
git submodule init
for i in $(git submodule | sed -e 's/.* //'); do
spath=$(git config -f .gitmodules --get submodule.$i.path)
surl=$(git config -f .gitmodules --get submodule.$i.url)
git clone --depth 1 $surl $spath
done
git submodule update
git-submodule "source"를 통해 git submodule add
이미 저장소가있는 서브 모듈을 처리 할 수있는 것처럼 보입니다 . 이 경우 ...
$ git clone $remote1 $repo
$ cd $repo
$ git clone --depth 5 $remotesub1 $sub1
$ git submodule add $remotesub1 $sub1
#repeat as necessary...
필요한 커밋이 서브 모듈 저장소에 있는지 확인하고 적절한 --depth를 설정했는지 확인하십시오.
편집 : 여러 수동 하위 모듈 클론을 사용하고 단일 업데이트를 수행 할 수 있습니다.
$ git clone $remote1 $repo
$ cd $repo
$ git clone --depth 5 $remotesub1 $sub1
#repeat as necessary...
$ git submodule update
Git 2.14.1 기준 버그 / 예기치 못한 / 불쾌한 행동 요약
shallow = true
in.gitmodules
only affectsgit clone --recurse-submodules
if theHEAD
of the remote submodule points to the required commit, even if the target commit is pointed to by a branch, and even if you putbranch = mybranch
on the.gitmodules
as well.Local test script. Same behaviour on GitHub 2017-11, where
HEAD
is controlled by the default branch repo setting:git clone --recurse-submodules https://github.com/cirosantilli/test-shallow-submodule-top-branch-shallow cd test-shallow-submodule-top-branch-shallow/mod git log # Multiple commits, not shallow.
git clone --recurse-submodules --shallow-submodules
fails if the commit is neither referenced by a branch or tag with a message:error: Server does not allow request for unadvertised object
.Local test script. Same behaviour on GitHub:
git clone --recurse-submodules --shallow-submodules https://github.com/cirosantilli/test-shallow-submodule-top-sha # error
I also asked on the mailing list: https://marc.info/?l=git&m=151863590026582&w=2 and the reply was:
In theory this should be easy. :)
In practice not so much, unfortunately. This is because cloning will just obtain the latest tip of a branch (usually master). There is no mechanism in clone to specify the exact sha1 that is wanted.
The wire protocol supports for asking exact sha1s, so that should be covered. (Caveat: it only works if the server operator enables uploadpack.allowReachableSHA1InWant which github has not AFAICT)
git-fetch allows to fetch arbitrary sha1, so as a workaround you can run a fetch after the recursive clone by using "git submodule update" as that will use fetches after the initial clone.
TODO test: allowReachableSHA1InWant
.
Are the canonical locations for your submodules remote? If so, are you OK with cloning them once? In other words, do you want the shallow clones just because you are suffering the wasted bandwidth of frequent submodule (re)clones?
If you want shallow clones to save local diskspace, then Ryan Graham's answer seems like a good way to go. Manually clone the repositories so that they are shallow. If you think it would be useful, adapt git submodule
to support it. Send an email to the list asking about it (advice for implementing it, suggestions on the interface, etc.). In my opinion, the folks there are quite supportive of potential contributors that earnestly want to enhance Git in constructive ways.
If you are OK with doing one full clone of each submodule (plus later fetches to keep them up to date), you might try using the --reference
option of git submodule update
(it is in Git 1.6.4 and later) to refer to local object stores (e.g. make --mirror
clones of the canonical submodule repositories, then use --reference
in your submodules to point to these local clones). Just be sure to read about git clone --reference
/git clone --shared
before using --reference
. The only likely problem with referencing mirrors would be if they ever end up fetching non-fast-forward updates (though you could enable reflogs and expand their expiration windows to help retain any abandoned commits that might cause a problem). You should not have any problems as long as
- you do not make any local submodule commits, or
- any commits that are left dangling by non-fast-forwards that the canonical repositories might publish are not ancestors to your local submodule commits, or
- you are diligent about keeping your local submodule commits rebased on top of whatever non-fast-forwards might be published in the canonical submodule repositories.
If you go with something like this and there is any chance that you might carry local submodule commits in your working trees, it would probably be a good idea to create an automated system that makes sure critical objects referenced by the checked-out submodules are not left dangling in the mirror repositories (and if any are found, copies them to the repositories that need them).
And, like the git clone
manpage says, do not use --reference
if you do not understand these implications.
# Full clone (mirror), done once.
git clone --mirror $sub1_url $path_to_mirrors/$sub1_name.git
git clone --mirror $sub2_url $path_to_mirrors/$sub2_name.git
# Reference the full clones any time you initialize a submodule
git clone $super_url super
cd super
git submodule update --init --reference $path_to_mirrors/$sub1_name.git $sub1_path_in_super
git submodule update --init --reference $path_to_mirrors/$sub2_name.git $sub2_path_in_super
# To avoid extra packs in each of the superprojects' submodules,
# update the mirror clones before any pull/merge in super-projects.
for p in $path_to_mirrors/*.git; do GIT_DIR="$p" git fetch; done
cd super
git pull # merges in new versions of submodules
git submodule update # update sub refs, checkout new versions,
# but no download since they reference the updated mirrors
Alternatively, instead of --reference
, you could use the mirror clones in combination with the default hardlinking functionality of git clone
by using local mirrors as the source for your submodules. In new super-project clones, do git submodule init
, edit the submodule URLs in .git/config
to point to the local mirrors, then do git submodule update
. You would need to reclone any existing checked-out submodules to get the hardlinks. You would save bandwidth by only downloading once into the mirrors, then fetching locally from those into your checked-out submodules. The hard linking would save disk space (although fetches would tend to accumulate and be duplicated across multiple instances of the checked-out submodules' object stores; you could periodically reclone the checked-out submodules from the mirrors to regain the disk space saving provided by hardlinking).
I created a slightly different version, for when it's not running at the bleeding edge, which not all projects do. The standard submodule additions did't work nor did the script above. So I added a hash lookup for the tag ref, and if it doesn't have one, it falls back to full clone.
#!/bin/bash
git submodule init
git submodule | while read hash name junk; do
spath=$(git config -f .gitmodules --get submodule.$name.path)
surl=$(git config -f .gitmodules --get submodule.$name.url)
sbr=$(git ls-remote --tags $surl | sed -r "/${hash:1}/ s|^.*tags/([^^]+).*\$|\1|p;d")
if [ -z $sbr ]; then
git clone $surl $spath
else
git clone -b $sbr --depth 1 --single-branch $surl $spath
fi
done
git submodule update
Reference to How to clone git repository with specific revision/changeset?
I have written a simple script which has no problem when your submodule reference is away from the master
git submodule foreach --recursive 'git rev-parse HEAD | xargs -I {} git fetch origin {} && git reset --hard FETCH_HEAD'
This statement will fetch the referenced version of submodule.
It is fast but you cannot commit your edit on the submodule (you have to fetch unshallow it before https://stackoverflow.com/a/17937889/3156509)
in full:
#!/bin/bash
git submodule init
git submodule foreach --recursive 'git rev-parse HEAD | xargs -I {} git fetch origin {} && git reset --hard FETCH_HEAD'
git submodule update --recursive
Shallow clone of a submodule is perfect because they snapshot at a particular revision/changeset. It's easy to download a zip from the website so I tried for a script.
#!/bin/bash
git submodule deinit --all -f
for value in $(git submodule | perl -pe 's/.*(\w{40})\s([^\s]+).*/\1:\2/'); do
mysha=${value%:*}
mysub=${value#*:}
myurl=$(grep -A2 -Pi "path = $mysub" .gitmodules | grep -Pio '(?<=url =).*/[^.]+')
mydir=$(dirname $mysub)
wget $myurl/archive/$mysha.zip
unzip $mysha.zip -d $mydir
test -d $mysub && rm -rf $mysub
mv $mydir/*-$mysha $mysub
rm $mysha.zip
done
git submodule init
git submodule deinit --all -f
clears the submodule tree which allows the script to be reusable.
git submodule
retrieves the 40 char sha1 followed by a path that corresponds to the same in .gitmodules
. I use perl to concatenate this information, delimited by a colon, then employ variable transformation to separate the values into mysha
and mysub
.
These are the critical keys because we need the sha1 to download and the path to correlate the url
in .gitmodules.
Given a typical submodule entry:
[submodule "label"]
path = localpath
url = https://github.com/repository.git
myurl
keys on path =
then looks 2 lines after to get the value. This method may not work consistently and require refinement. The url grep strips any remaining .git
type references by matching to the last /
and anything up to a .
.
mydir
is mysub
minus a final /name
which would by the directory leading up to the submodule name.
Next is a wget
with the format of downloadable zip archive url. This may change in future.
Unzip the file to mydir
which would be the subdirectory specified in the submodule path. The resultant folder will be the last element of the url
-sha1
.
Check to see if the subdirectory specified in the submodule path exists and remove it to allow renaming of the extracted folder.
mv
rename the extracted folder containing our sha1 to its correct submodule path.
Delete downloaded zip file.
Submodule init
This is more a WIP proof of concept rather than a solution. When it works, the result is a shallow clone of a submodule at a specified changeset.
Should the repository re-home a submodule to a different commit, re-run the script to update.
The only time a script like this would be useful is for non-collaborative local building of a source project.
참고URL : https://stackoverflow.com/questions/2144406/how-to-make-shallow-git-submodules
'Programming' 카테고리의 다른 글
가동 중지 시간없이 ASP.NET 응용 프로그램을 배포하는 방법 (0) | 2020.07.06 |
---|---|
Mercurial에서 닫힌 지점을 다시 열 수 있습니까? (0) | 2020.07.06 |
Python, 유니 코드 및 Windows 콘솔 (0) | 2020.07.06 |
Chrome 개발 도구 : 자바 스크립트의 [VM] 파일 (0) | 2020.07.06 |
mac OS X에서 strace -feopen <command>와 동일 (0) | 2020.07.06 |