2014-10-01 11 views
17

In Anbetracht einer recent question on SO und eines ähnlichen Szenarios bei der Arbeit, frage ich mich, warum gibt es keine Option in git clone so, dass der HEAD Zeiger des neu erstellten Zweigs auf einen angegebenen Commit zeigen? In dieser Frage versucht OP, Anweisungen zu den spezifischen Commits zu geben, die seine Benutzer verwenden sollten, während in meinem Fall bei der Arbeit versucht wird, ein bestimmtes Commit zu klonen, das einem Submodul entspricht, an dem wir interessiert sind.Warum gibt es keine Git Clone Specific Commit Option?

Beachten Sie, dass es sich bei dieser Frage nicht um How To Clone To A Particular Version mit reset handelt; aber über warum gibt es nicht?

Antwort

18

Zwei Antworten bisher (zu der Zeit, ich schrieb dies, jetzt gibt es mehr) sind richtig in dem, was sie sagen, aber nicht wirklich beantworten die "warum" Frage. Natürlich ist die "Warum" -Frage wirklich schwer zu beantworten, außer von den Autoren der verschiedenen Bits von Git (und selbst dann, was wäre, wenn zwei häufige Git-Mitwirkende zwei verschiedene Antworten geben würden?).

Dennoch, in Anbetracht der "Philosophie" Git so, im Allgemeinen, die verschiedenen Übertragungsprotokolle arbeiten durch die Nennung einer Referenz. Wenn sie eine SHA-1 bereitstellen, ist es die SHA-1 dieser Referenz. Für jemanden, der nicht bereits direkten Zugriff (z. B. Befehlszeile) auf das Repository hat, erlaubt es keiner der eingebauten Befehle, auf Commits nach ID zu verweisen.Das nächste, was ich zu einem Grunde finden kann dies-und es ist eigentlich ein guter Grund -ist dieses Bit in the git upload-archive documentation:

SECURITY

Um die Privatsphäre von Objekten zu schützen die aus history entfernt wurden, aber möglicherweise noch nicht bereinigt wurden, verhindert git-upload-archive das Bereitstellen von Archiven für Commits und Bäume, die nicht über die Refs des Repositorys erreichbar sind. Da jedoch die Berechnung Objekt Erreichbarkeit ist rechnerisch teuer, git-Upload-Archiv implementiert ein strenger aber einfacher zu Check Satz von Regeln ...

Es ist jedoch weiter sagt:

Wenn die Konfigurationsoption uploadArchive.allowUnreachable wahr ist, werden diese Regeln ignoriert, und Clients können beliebige sha1-Ausdrücke verwenden. Diese ist nützlich, wenn Sie sich nicht um die Privatsphäre nicht erreichbarer Objekte kümmern, oder wenn Ihre Objektdatenbank bereits für den Zugriff über non-smart-http öffentlich verfügbar ist.

die besonders interessant ist, da git clone alle erreichbaren Objekte in erster Linie bekommt, nach welcher den lokalen Klon trivialer eine Festschreibung von SHA-1-ID überprüfen kann (und einen lokalen Zweig Namen diese ID zeigen erstellen, wenn gewünscht oder lassen Sie Ihren Klon einfach im Modus "Abgetrennte HEAD".

Angesichts dieser zwei Querströmungen, denke ich, ist die wirkliche Antwort auf "warum", an diesem Punkt ist "niemand kümmert sich genug, um es hinzuzufügen". :-) Das Privacy-Argument ist gültig, aber es gibt keinen Grund, dass git clone nach dem Klonen keine Commit-ID auschecken konnte, genauso wie es gesagt werden kann, um einen anderen Zweig als master mit git clone -b ... auszuchecken. Der einzige Nachteil beim Erlauben von -b sha1 ist, dass Git nicht überprüfen kann, ob sha1 empfangen wird (bevor der Klonprozess beginnt). Es kann Prüfreferenzwert Namen, da diese (zusammen mit ihren Zweigspitzen oder anderem SHA-1-Wert) nach vorne übertragen werden, so git clone -b nonexistentbranch ssh://... endet schnell und erstellt nicht die Kopie:

fatal: Remote branch nonexistentbranch not found in upstream origin 
fatal: The remote end hung up unexpectedly 

Wenn -b zulässigen ID, du würdest den ganzen Klon bekommen, dann müsste er dir sagen: "Oh Gott, Entschuldigung, ich kann den Ausweis nicht auschecken, ich überlasse dir stattdessen den Meister" oder was auch immer. (Das ist mehr oder weniger das, was jetzt mit einem kaputten Submodul passiert.)


Während git upload-archivejetzt diese „Privatsphäre“ Regel erzwingt, war dies nicht immer der Fall (es ist in der Version 1.7 eingeführt wurde .8.1); und viele (die meisten?) git-Webserver, einschließlich der mit Git selbst verteilten, erlauben die Betrachtung nach beliebigen IDs. Dies ist wahrscheinlich, warum allowUnreachable zu upload-archive ein paar Jahre nach dem "Nur durch Ref Name" Code hinzugefügt wurde (aber beachten Sie, dass Releases von Git nach 1.7.8 und vor 2.0.0 keine Möglichkeit haben, die Regeln zu lockern). Während also die Idee "Sicherheit" gültig ist, gab es einen Zeitraum (vor 1.7.8.1), als es nicht durchgesetzt wurde.

Es gibt zahlreiche Möglichkeiten, angeblich private Daten aus einem Git-Repository zu "lecken". Eine neue Datei, Documentation/transfer-data-leaks, wird in Git 2.11.1 erscheinen, während Git 2.11.0 einige interne Features hinzugefügt hat (siehe commit 722ff7f87 unter anderen), um Objekte sofort fallen zu lassen, aber nicht akzeptiert. Solche Objekte werden schließlich Müll gesammelt, aber das lässt sie für die Dauer ausgesetzt. Eigentlich

standardmäßig git clone macht einen lokalen Check-out der Branche es denkt, geht mit der HEAD Referenz der Fernbedienung. Normalerweise ist das aber master.

+0

Würde https://github.com/git/git/blob/565301e41670825ceedf75220f2918ae76831240 /Documentation/git-upload-archive.txt#L26-L31 ein geeigneter Link sein? – VonC

+0

@VonC: ooh, ja, danke :-) – torek

+0

Das 'allowUnreachable' Geschäft scheint ziemlich neu (Git 2.0+): https://github.com/git/git/commit/7671b63211712e5163ed46d4c93d0b75680c886c – VonC

3

Wenn Ihre spezifische Festschreibung von einem Zweig Bezug genommen wird, können Sie eine tun:

git clone -b yourBranch /url/of/the/repo 

Das geklonte Repo wird direkt an dem von diesem Zweig verwiesen commit.

+0

Rechts. In meinem Fall sind die [Submodule] (https://github.com/cloudfoundry/cf-release/tree/master/src), mit denen wir arbeiten wollen, bestimmten (älteren) Commits in 'master' zugeordnet. –

+0

Sie können jederzeit einen Zweig der älteren Commits erstellen - 'git branch clone_me OLD_SHA' –

+0

Eine andere Lösung, die anderswo vorgeschlagen wird, ist fork, dann erstellen Sie ein Tag mit dem gewünschten SHA und verwenden Sie dann git Submodule, um das getaggte SHA zu verfolgen. – CMCDragonkai

7

Das Klonen eines Repos ist ein anderer Vorgang als das Auschecken. Sie "klonen kein bestimmtes Commit". Aus praktischen Gründen können Sie einen bestimmten bereits vorhandenen Zweig zur gleichen Zeit klonen und dann auschecken, da dies die meisten Benutzer wünschen. Wenn das nicht Ihre Bedürfnisse (kein Zweig für die speziellen SHA Sie wollen) trifft nur verwenden oder Alias ​​irgendeine Form von

git clone -n <some repo> && cd <some repo> && git checkout SHA 
4

Wie die anderen Antworten sagen, dies in der Regel nicht viel von einem Problem, aber sie don Sag nicht, warum du ein bestimmtes Commit nicht klonen kannst. Die Antwort ist Sicherheit.

Wenn Sie versehentlich vertrauliche Informationen übertragen und dann einen festen Verlauf erzwingen, werden die Commits mit den vertraulichen Informationen weiterhin auf dem Server gespeichert, bis der Garbage Collector des Servers erkennt, dass er nicht mehr benötigt wird. Wenn der Hash bekannt ist (er könnte zum Beispiel in Protokollen verfügbar sein), könnte ein böswilliger Benutzer das spezifische Commit anfordern, das nicht gepusht worden sein sollte, selbst wenn Sie dies überprüfen konnten, als Sie den festen Verlauf erzwingen, niemand hatte diese Commits schon abgeholt.

Wenn Sie sicherstellen, dass Sie nur aus Refs klonen können, wird sichergestellt, dass nur "erreichbare" Commits an die Clients gesendet werden.

+0

Was würde einen böswilligen Benutzer davon abhalten, einen neuen Zweig hochzuziehen, der auf diese Commit-ID verweist? (Der Client kann fröhlich einen neuen Zweig erstellen, der auf einen Commit verweist, den der Server bereits hat, ohne dass er irgendwelche anderen Commits hochschieben muss.) Der böswillige Benutzer könnte dann den vertraulichen Commit klonen und erhalten. –

+0

@EdwardThomson Vermutlich hätte ein böswilliger Benutzer keinen Push-Zugriff, aber einen fairen Punkt. – hvd

+0

Ich vermute, dass die Idee ist, dass der Klon-Vorgang diejenigen Commits herausfiltern wird, die nicht zugänglich sein sollten? Wenn ja, warum wäre es nicht möglich, dies auf dem Server zu tun, anstatt Bandbreite und kostbare Zeit (sowie Speicherplatz) zu verschwenden, indem Sie die gewünschten Commits an den Server senden? Ich beobachte gerade die Fortschrittsanzeige eines Linux-Kernel-Klons, der sich mit Verzweiflung vorwärts bewegt, wissend, dass das Commit, das ich möchte, weit zurückliegt ... – RJVB