Wie kann man ein bestimmtes Commit mit Tiefe 1 flach klonen?

79

Ist es möglich, ein bestimmtes Commit in einem Repository flach zu klonen, dh mit Tiefe 1? Etwas wie

git clone http://myrepo.git 728a4d --depth 1

um den Repository-Status zu erhalten, wie er beim Commit mit SHA ist 728a4d...?

Die Motivation besteht darin, zu vermeiden, dass das gesamte Repository geklont werden muss, und dann dieses bestimmte Commit zu überprüfen, wenn wir nur an dem Status des Repositorys bei diesem bestimmten Commit interessiert sind.

Kinn
quelle
Mögliches Duplikat von Wie klone ich ein Git-Repository mit einer bestimmten Revision / einem bestimmten Änderungssatz?
Ciro Santilli 法轮功 冠状 病 六四 事件 14

Antworten:

76

Ab Git 2.5.0 (das sowohl auf Client- als auch auf Serverseite verfügbar sein muss ) können Sie uploadpack.allowReachableSHA1InWant=trueauf der Serverseite festlegen, dass bestimmte SHA1s abgerufen werden sollen:

git init
git remote add origin <url>
git fetch --depth 1 origin <sha1>
git checkout FETCH_HEAD

Beachten Sie, dass ich keine Syntax gefunden habe, mit der ich dies git clonedirekt tun kann.

sschuberth
quelle
3
Zumindest mit Github funktioniert das nicht. Ich konnte nicht für github.com/Seldaek/monolog/commit/… holen . git fetch --depth 1 origin d6be96bc...Showsfatal: Couldn't find remote ref d6be96bc...
Kirby
9
Richtig, GitHub hat nur aktiviert allowTipSHA1InWant, aber weder allowReachableSHA1InWantnoch allowAnySHA1InWant.
Sschuberth
2
Als ich damit herumspielte, stellte ich fest, dass es nur auf einer sehr modernen Version des Git-Clients funktionierte. Sogar Git 2.17 hat bei mir nicht funktioniert. Ich habe Git um 2.24 Uhr wieder aufgebaut und das hat funktioniert.
Eyal
1
Arbeitete für mich mit 2.27.0.windows.1 auf github.com/dotnet/aspnetcore @ 62c098bc170f50feca15916e81cb7f321ffc52ff
JJS
1
Dies scheint jetzt auf GitHub zu funktionieren.
Vortico
23

HINWEIS: Mein Beispiel hilft nicht beim Klonen mit einem Commit-Hash, aber es hilft beim Klonen eines Tags und verfügt über ein leichtes Repository.

Wenn Sie nur ein Commit in Ihrem "Klon" haben müssen und Commit-Hash verwenden möchten, lautet die kurze Antwort NEIN .

Ich verwende diese Befehlskonstruktion (getestet in v2.13.2.windows.1 ) für Tags:

git clone --depth 1 [email protected]:VENDOR/REPO.git --branch 1.23.0 --single-branch

Vollständiges Beispiel:

$ git clone --depth 1 [email protected]:Seldaek/monolog.git --branch 1.23.0 --single-branch
Cloning into 'monolog'...
remote: Counting objects: 201, done.
remote: Compressing objects: 100% (188/188), done.
remote: Total 201 (delta 42), reused 32 (delta 5), pack-reused 0
Receiving objects: 100% (201/201), 190.30 KiB | 0 bytes/s, done.
Resolving deltas: 100% (42/42), done.
Note: checking out 'fd8c787753b3a2ad11bc60c063cff1358a32a3b4'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

$ cd monolog

.gitdir Größe ( 267K vs 2.6M bei Verwendung von full clone):

$ du -h --max-depth=0 .git
267K    .git

Ich möchte bezeichnen, --branchkann ein Tag / Zweig nehmen.

https://git-scm.com/docs/git-clone#git-clone---branchltnamegt

--branch kann auch Tags nehmen und den HEAD bei diesem Commit im resultierenden Repository trennen.

UPD

Kurz gesagt, es kann "refs" dauern. Lesen Sie hier mehr: Was bedeutet die Git-Fehlermeldung "Server erlaubt keine Anforderung für nicht beworbenes Objekt"?

Auch gibt es keine Tricks wie:

git fetch --depth 1 origin <COMMIT_HASH>

Danke @BenjiWiebe, dass du mich auf meinen Fehler hingewiesen hast.

Kirby
quelle
2
Eine Million positive Stimmen dafür. Viel zu viele Leute behaupten, dies sei nicht möglich.
Jooks
3
--branchunterstützt keine Commits, nur Filialnamen ... das löst es überhaupt nicht. Da ist es nicht wahr.
Abourget
1
Kirby, ich versuche das jetzt und es funktioniert nicht für Commits , wie @abourget sagt. Vielleicht funktioniert es für Tags und Zweige, aber ich versuche es mit Commit-Hashes und das funktioniert nicht.
BenjiWiebe
@ BenjiWiebe, ich verstehe, Leute. Ja, anscheinend kann GIT kein bestimmtes Commit bestimmen. : - / Ich werde es tiefer graben.
Kirby
@ BenjiWiebe, daher gibt es leider keine Möglichkeit, Commit-Hash zu verwenden. Einfach doppelt prüfen.
Kirby
6

Die sofortige Antwort lautet: Sie können nicht.
Warum? Eine ausführliche Erklärung finden Sie hier: Warum gibt es keine Git Clone-spezifische Commit-Option?

Was kannst du sonst noch tun?

Wie klone ich ein Repository für ein bestimmtes Commit? (vollständiger Klon)

# Create empty repository to store your content
git clone <url>
git reset <sha-1> --hard

Mehr Info:

Wie klone ich einen einzelnen Zweig?

git clone <url> --branch <branch_name> --single-branch <folder_name>

Wie klone ich nur das letzte Commit eines bestimmten Zweigs?

git clone <url> --depth=1 --branch <branch_name> --single-branch <folder_name>

Wie kann man ein bestimmtes Commit mit Tiefe 1 flach klonen?

Wie @sschuberth auskommentierte: --depthimpliziert --single-branch.

Verwenden Sie anstelle des Klonens den Befehl fetch:

# fetch a commit (or branch or tag) of interest
# In this case you will have the full history of this commit
git fetch origin <sha1>
CodeWizard
quelle
4
Dies beantwortet die Frage nicht. Der Fragesteller möchte wissen, wie ein einzelnes Commit ausgecheckt werden kann, auch wenn kein Ref direkt darauf verweist.
Joseph K. Strauss
Tut mir leid, ich habe es verpasst, irgendwie habe ich verstanden, dass er das neueste Commit braucht. Antwort aktualisieren. Vielen Dank
CodeWizard
--depthimpliziert --single-branch, so dass Sie es in diesem Fall fallen lassen könnten.
Sschuberth
Hat git fetchakzeptieren tatsächlich einen SHA1 für refspec?
Phil Frost
Nee. Es wird einfach die Daten "heruntergeladen", die mit dem Namen des Zweigs
übereinstimmen
5

Versuchen Sie es mit whilein bash:

git clone --depth=1 $url
i=1; while ! git show $sha1; do git fetch --depth=$((i+=1)); done

Dies ist ziemlich langsam, da jedes Commit einzeln abgerufen wird. Sie könnten das Inkrement erhöhen (um Commits in Stapeln abzurufen und die Leistung über ein Netzwerk zu verbessern), aber es ist immer noch ein Brute-Force-Ansatz.

Corin
quelle
Warum stimmen die Stimmen ab? ... Ich musste das tatsächlich tun und meine Lösung hat es geschafft!
Corin
Was ist, wenn Sie ein Commit vor Jahren wünschen oder das es nicht mehr gibt?
Daan Bakker
@DaanBakker, wenn das Commit nicht mehr existiert, besteht die einzige Möglichkeit, dies festzustellen, darin, das gesamte Remote-Repository abzurufen. Wenn es nicht vorhanden ist und keine anderen Klone vorhanden sind, befinden Sie sich leider in einer Sackgasse.
Corin