Wie klone ich ein Git-Repository mit einer bestimmten Revision / einem bestimmten Änderungssatz?

393

Wie kann ich das Git-Repository mit einer bestimmten Revision klonen, wie ich es normalerweise in Mercurial mache:

hg clone -r 3 /path/to/repository
John
quelle
3
Nicht spezifisch für Änderungssätze oder Revisionen, aber das Klonen der neuesten in einem bestimmten Zweig kann genauso effektiv sein, dh git clone -b 10.1 https://github.com/MariaDB/server.git --depth=1 mariadb-server-src
MrMesees
Mögliches Duplikat von Download eines bestimmten Tags mit Git
SlightlyCuban
Möchten Sie, dass der Verlauf flach ist, dh nur Revision 3 in Ihrem Beispiel enthält, oder auch die Eltern?
sschuberth
Wenn das betreffende Repository aus einem anderen Repository geklont wird und Sie dieses interne Repo zu einem bestimmten Zeitpunkt klonen möchten, tun Git-Submodule genau das auf automatische Weise.
J0hnG4lt

Antworten:

202

UPDATE 2 Seit Git 2.5.0 kann die unten beschriebene Funktion serverseitig mit Konfigurationsvariablen aktiviert werden. Hier aktivieren uploadpack.allowReachableSHA1InWantdie GitHub-Funktionsanforderung und das GitHub-Commit diese Funktion . Beachten Sie, dass einige Git-Server diese Option standardmäßig aktivieren, z. B. Bitbucket Server hat sie seit Version 5.5+ aktiviert . In dieser Antwort auf Stackexchange finden Sie ein Beispiel zum Aktivieren der Konfigurationsoption.

UPDATE 11.7 < v < 2.5 Verwenden Sie für Git-Versionen den Git-Klon und den Git-Reset, wie in der Antwort von Vaibhav Bajpai beschrieben

Wenn Sie nicht das vollständige Repository abrufen möchten, sollten Sie es wahrscheinlich nicht verwenden clone. Sie können immer nur Abrufen verwenden, um den Zweig auszuwählen, den Sie abrufen möchten. Ich bin kein HG-Experte, daher kenne ich die Details nicht, -raber in Git können Sie so etwas tun.

# make a new blank repository in the current directory
git init

# add a remote
git remote add origin url://to/source/repository

# fetch a commit (or branch or tag) of interest
# Note: the full history up to this commit will be retrieved unless 
#       you limit it with '--depth=...' or '--shallow-since=...'
git fetch origin <sha1-of-commit-of-interest>

# reset this repository's master branch to the commit of interest
git reset --hard FETCH_HEAD
CB Bailey
quelle
32
Ich denke nicht, dass es git fetch origin <sha1>funktioniert; Es scheint, als müssten Sie eine benannte Referenz wie ein Tag oder einen Zweignamen übergeben. Siehe kerneltrap.org/mailarchive/git/2009/1/13/4707444
artur
48
@artur: Du denkst nicht, dass es funktioniert, oder du hast es versucht und es funktioniert nicht?
CB Bailey
37
Mit Git 1.4 stellte ich fest, dass ich mit dem git fetch origin <SHA1>zu jeder gewünschten Revision wechseln konnte, nachdem ich den Master von der Fernbedienung abgerufen und reset --hardden Zweig lokal instanziiert hatte. Ich konnte die einzelnen Revisionen nicht direkt abrufen. Mit Git 1.7 git fetch origin <SHA1>funktionierte nicht, wie von @artur berichtet; Sie müssen verwenden, git checkout <SHA1>gefolgt von einem reset --hard.
Joe McMahon
6
Das Abrufen mit SHA-1 funktioniert nur mit den Protokollen http und rsync. Siehe kerneltrap.org/mailarchive/git/2009/1/14/4716044/…
CharlesB
23
Diese Antwort ist veraltet. Dies funktioniert weder mit Git 1.7 noch mit Git 1.8, weder mit https: // noch mit dem SSH-Protokoll. ("Remote-Referenz konnte nicht gefunden werden df44398762393c67af487edeb0831ad9579df4aa" - es ist keine Referenz, es ist ein Commit.)
Paŭlo Ebermann
839
$ git clone $URL
$ cd $PROJECT_NAME
$ git reset --hard $SHA1

Um noch einmal zum letzten Commit zurückzukehren

$ git pull
Vaibhav Bajpai
quelle
13
Dies funktioniert nur, wenn sich das Commit im Hauptzweig befindet. Andernfalls wird die lokale Referenz durcheinander gebracht. Warum git zurücksetzen und nicht git checkout?
Joky
72
Dies ist keine gute Option für große Repos, da es alles zieht.
Inkognito
1
Diese Lösung sollte oben sein. Niemand kümmert sich darum, dass es "nicht optimal" ist, darum hat das OP gebeten. Konkret: "Wie klone ich das Git-Repository mit einer bestimmten Revision?"
Florian Segginger
20
@FlorianSegginger Wenn ich eine bestimmte Revision klonen möchte, möchte ich wahrscheinlich nicht alles klonen, sondern nur diese Revision. Für mich war das die Frage. Diese Lösung beantwortet eine andere Frage: "Wie kann ich eine bestimmte Revision in meinem Repo anzeigen?". Das gesamte Repo zu holen ist genau das, was viele Leute hier vermeiden wollen.
Renato
1
Geht IMHO nicht auf die eigentliche Frage ein, da ich durch die Möglichkeit, eine Revision während des Klonens anzugeben, auch die --depthfür große Repos sehr wichtige verwenden kann. Diese Lösung erfordert das Ziehen aller Objekte und das Zurücksetzen auf eine frühere Version. Dies ist sehr zeitaufwändig und verschwendet die Netzwerkbandbreite.
void.pointer
54

Das Klonen eines Git-Repositorys klont treffend das gesamte Repository: Es gibt keine Möglichkeit, nur eine Revision zum Klonen auszuwählen. Sobald Sie jedoch ausgeführt haben, git clonekönnen Sie eine bestimmte Revision auschecken, indem Sie dies tun checkout <rev>.


quelle
4
Ich möchte nicht nur eine Revision klonen. Ich möchte nur die Grenze des Klonens angeben. Mit anderen Worten, ich möchte alles bis zur angegebenen Revision klonen.
John
6
Das kannst du nicht machen. git clonegreift nach dem gesamten Repository. Sobald Sie es haben, können Sie eine bestimmte Revision auschecken.
4
Eine Sache zu beachten; Git ist im Allgemeinen ziemlich effizient beim Speichern des Verlaufs. Es ist also nicht so, als würden Sie viel Platz sparen, indem Sie nur die Hälfte der Revisionen klonen.
Amber
Es geht nicht darum, "Platz zu sparen" - es geht nur darum, eine bestimmte Revision zu erreichen - etwa wenn eine neue Änderung einen Fehler verursacht, und deshalb möchte ich diese neueste Änderung nicht - Sie sagen, Git kann das nicht diese? Das kann nicht richtig sein - warum überhaupt Quellcodeverwaltung, wenn Sie nicht auf eine ältere Version zurücksetzen können?
BrainSlugs83
1
"Es gibt keine Möglichkeit, nur eine Revision zum Klonen auszuwählen" - ja, es gibt:git clone --single-branch ...
Morxa
33

Um nur ein bestimmtes Commit für einen bestimmten Zweig oder ein bestimmtes Tag zu klonen, verwenden Sie:

git clone --depth=1 --branch NAME https://github.com/your/repo.git

Leider NAMEkann nur Zweigstellenname oder Tag-Name sein (kein SHA festschreiben).

Lassen Sie das --depthFlag weg , um den gesamten Verlauf herunterzuladen, und überprüfen Sie dann den Zweig oder das Tag:

git clone --branch NAME https://github.com/your/repo.git

Dies funktioniert mit der neuesten Version von git (ich habe es mit der Version gemacht 2.18.0).

Peter Kovac
quelle
aber nicht auf älteren Version 2.17.1
RzR
4
Dies erfordert mehr Upvotes. Dies ist viel besser als andere veraltete Antworten.
Étienne
32

Wenn Sie meinen, Sie möchten alles von Anfang an bis zu einem bestimmten Punkt abrufen, ist Charles Baileys Antwort perfekt. Wenn Sie das Gegenteil tun und eine Teilmenge des Verlaufs ab dem aktuellen Datum abrufen möchten, können Sie verwenden, git clone --depth [N] wobei N die Anzahl der gewünschten Umdrehungen des Verlaufs ist. Jedoch:

--Tiefe

Erstellen Sie einen flachen Klon mit einem Verlauf, der auf die angegebene Anzahl von Revisionen gekürzt wurde. Ein flaches Repository weist eine Reihe von Einschränkungen auf (Sie können es nicht klonen oder abrufen oder von dort hineinschieben oder hineinschieben), ist jedoch ausreichend, wenn Sie nur an der jüngsten Geschichte eines großen Projekts mit einer langen Geschichte interessiert sind und dies möchten Fixes als Patches einsenden.

Walter Mundt
quelle
4
Neuere Versionen von Git haben flache Klone verbessert, und Sie können daraus ziehen und schieben.
Orion78 vom
26

Nur um es zusammenzufassen (git v. 1.7.2.1):

  1. Mach einen Stammgast, git clonewo du das Repo willst (bringt alles auf den neuesten Stand - ich weiß, nicht was gewünscht wird, wir kommen dorthin)
  2. git checkout <sha1 rev> der Drehzahl, die Sie wollen
  3. git reset --hard
  4. git checkout -b master
phill
quelle
6
Was machen die Schritte 3 und 4?
BrainSlugs83
Schritt 4 hat bei mir nicht funktioniert, aber bis zu Schritt 3 hat es geschafft - Danke
Gene Bo
@ BrainSlugs83: Schritt 4 erstellt einen lokalen Zweig namens masterund wechselt zu diesem.
LarsH
3
@phill: Warum die git reset --hard? In den Dokumenten dazu heißt es: "Setzt den Index und den Arbeitsbaum zurück. Alle Änderungen an nachverfolgten Dateien im Arbeitsbaum seit <commit> [standardmäßig HEAD, das jetzt ist <sha1 rev>] werden verworfen." Aber zu diesem Zeitpunkt haben wir seit dem Klonen keine Änderungen vorgenommen. Was ist also der Zweck? Schneidet es den aktuellen Zweig bei ab <sha1 rev>?
LarsH
19

TL; DR - Erstellen Sie einfach ein Tag im Quell-Repository für das Commit, zu dem Sie klonen möchten, und verwenden Sie das Tag im Befehl fetch. Sie können das Tag später aus dem Original-Repo löschen, um es zu bereinigen.

Nun, es ist 2014 und es sieht so aus, als ob Charles Baileys akzeptierte Antwort aus dem Jahr 2010 mittlerweile wirklich veraltet ist und die meisten (alle?) Der anderen Antworten beinhalten das Klonen, was viele Menschen zu vermeiden hoffen.

Mit der folgenden Lösung wird das erreicht, wonach das OP und viele andere suchen. Auf diese Weise können Sie eine Kopie eines Repositorys einschließlich des Verlaufs erstellen, jedoch nur bis zu einem bestimmten Commit.

Hier sind die Befehle, die ich mit git Version 2.1.2 verwendet habe, um ein lokales Repo (dh ein Repository in einem anderen Verzeichnis) bis zu einem bestimmten Punkt zu klonen:

# in the source repository, create a tag against the commit you want to check out
git tag -m "Temporary tag" tmptag <sha1>

# create a new directory and change into that directory
cd somewhere_else;mkdir newdir;cd newdir

# ...and create a new repository
git init

# add the source repository as a remote (this can be a URL or a directory)
git remote add origin /path/to/original/repo

# fetch the tag, which will include the entire repo and history up to that point
git fetch origin refs/tags/tmptag

# reset the head of the repository
git reset --hard FETCH_HEAD

# you can now change back to the original repository and remove the temporary tag
cd original_repo
git tag -d tmptag

Hoffentlich funktioniert diese Lösung noch einige Jahre! :-)

JamesG
quelle
2
Dies ist eine gute Idee von Ihnen als Eigentümer des Repos, nicht sicher, ob es mit öffentlichen Repos funktioniert, die Sie nicht pflegen
Suhaib
18

Sie können einfach verwenden git checkout <commit hash>

in dieser Reihenfolge

bash git clone [URLTORepository] git checkout [commithash]

Commit-Hash sieht folgendermaßen aus: "45ef55ac20ce2389c9180658fdba35f4a663d204"

M.Othman
quelle
wie vorher - warum nach dem Klonen auschecken. Sobald Sie geklont haben, haben Sie den gesamten Verlauf im lokalen Repo. Warum hat diese Antwort zu viele positive Stimmen?
Dmitry Perfilyev
2

Die Verwendung von 2 der oben genannten Antworten ( Wie klone ich ein Git-Repository mit einer bestimmten Revision / einem bestimmten Änderungssatz? Und Wie klone ich ein Git-Repository mit einer bestimmten Revision / einem bestimmten Änderungssatz? ) Hat mir geholfen, eine endgültige Antwort zu finden. Wenn Sie bis zu einem Punkt klonen möchten, muss dieser Punkt ein Tag / Zweig sein, nicht nur ein SHA, oder der FETCH_HEAD wird verwirrt. Wenn Sie nach dem Git-Abrufsatz einen Zweig- oder Tag-Namen verwenden, erhalten Sie eine Antwort. Wenn Sie einfach einen SHA-1 verwenden, erhalten Sie keine Antwort.
Folgendes habe ich getan: - Erstellen Sie einen voll funktionsfähigen Klon des vollständigen Repos aus dem tatsächlichen Ursprung

cd <path to create repo>
git clone git@<our gitlab server>:ui-developers/ui.git 

Erstellen Sie dann an der interessanten Stelle eine lokale Niederlassung

git checkout 2050c8829c67f04b0db81e6247bb589c950afb14
git checkout -b origin_point

Erstellen Sie dann mein neues leeres Repo mit meiner lokalen Kopie als Ursprung

cd <path to create repo>
mkdir reduced-repo
cd reduced-repo
git init
git remote add local_copy <path to create repo>/ui
git fetch local_copy origin_point

Zu diesem Zeitpunkt erhielt ich diese Antwort. Ich stelle es fest, denn wenn Sie anstelle des obigen Zweigs einen SHA-1 verwenden, passiert nichts. Die Antwort bedeutet also, dass es funktioniert hat

/ var / www / html / ui-hacking $ git fetch local_copy origin_point
remote: Objekte zählen: 45493, fertig.
remote: Objekte komprimieren: 100% (15928/15928), fertig.
Remote: Insgesamt 45493 (Delta 27508), wiederverwendet 45387 (Delta 27463)
Empfangsobjekte: 100% (45493/45493), 53,64 MiB | 50,59 MiB / s, fertig.
Auflösen von Deltas: 100% (27508/27508), erledigt.
Aus / var / www / html / ui
 * branch origin_point -> FETCH_HEAD
 * [neuer Zweig] origin_point -> origin / origin_point

In meinem Fall musste ich das dann wieder auf Gitlab setzen, als neues Repo, also tat ich es

git remote add origin git@<our gitlab server>:ui-developers/new-ui.git

Was bedeutete, dass ich mein Repo vom origin_point aus neu erstellen konnte, indem ich git --git-dir=../ui/.git format-patch -k -1 --stdout <sha1> | git am -3 -kCherry Pick aus der Ferne verwendete und dann git push origindas gesamte Los zurück in sein neues Zuhause hochlud .

Hoffe das hilft jemandem

Sibaz
quelle
Können Sie erklären, was Sie mit "FETCH_HEAD wird verwirrt" meinen? Und wie unterscheiden Sie git fetch local_copy origin_pointsich von JamesGs git fetch origin refs/tags/tmptag?
not2qubit
Das git fetch local_copy origin_pointlassen Sie sich in einem Zustand mit einem leeren reduced-repoVerzeichnis, nur ein enthält .git. In dieser Anleitung fehlt noch etwas ...
not2qubit
2

Meine Version war eine Kombination aus akzeptierten und am besten bewerteten Antworten. Aber es ist ein bisschen anders, weil jeder SHA1 verwendet, aber niemand sagt Ihnen, wie Sie es bekommen

$ git init
$ git remote add <remote_url>
$ git fetch --all

Jetzt können Sie alle Zweige und Commits sehen

$ git branch -a
$ git log remotes/origin/master <-- or any other branch

Schließlich kennen Sie SHA1 des gewünschten Commits

git reset --hard <sha1>
vladkras
quelle
1

Ich verwende dieses Snippet mit GNU make, um Revisions-Tags, Zweige oder Hashs zu schließen

Es wurde auf Git Version 2.17.1 getestet

${dir}:
    mkdir -p ${@D}
    git clone --recursive --depth 1 --branch ${revison} ${url} ${@} \
 || git clone --recursive --branch ${revison} ${url} ${@} \
 || git clone ${url} ${@}
    cd ${@} && git reset --hard ${revison}
    ls $@




RzR
quelle
0

git clone https://github.com/ORGANIZATION/repository.git (Klonen Sie das Repository)

cd repository (navigate to the repository)

git fetch origin 2600f4f928773d79164964137d514b85400b09b2

git checkout FETCH_HEAD

JeffDropsIT
quelle
2
Warum holen, nachdem Sie geklont haben? Sobald Sie geklont haben, haben Sie den gesamten Verlauf im lokalen Repo. Warum hat diese Antwort zwei positive Stimmen?
Madhairsilence
0
# clone special tag/branch without history
git clone  --branch=<tag/branch> --depth=1 <repository>


# clone special revision with minimal histories
git clone --branch <branch> <repository> --shallow-since=yyyy-MM-ddTHH:mm:ss  # get the commit time
cd <dir>
git reset --hard <revision> 

Sie können keine Revision ohne Verlauf erhalten, wenn sie nicht uploadpack.allowReachableSHA1InWant=trueauf der Serverseite festgelegt ist. Sie können jedoch ein Tag dafür erstellen und stattdessen das spezielle Tag klonen.

Wongoo
quelle
-3

Es ist einfach. Sie müssen nur den Upstream für den aktuellen Zweig einstellen

$ git clone repo
$ git checkout -b newbranch
$ git branch --set-upstream-to=origin/branch newbranch
$ git pull

Das ist alles

NEOJPK
quelle
-4
git clone -o <sha1-of-the-commit> <repository-url> <local-dir-name>

gitverwendet das Wort originanstelle von im Volksmund bekanntrevision

Es folgt ein Ausschnitt aus dem Handbuch $ git help clone

--origin <name>, -o <name>
    Instead of using the remote name origin to keep track of the upstream repository, use <name>.
hell_ical_vortex
quelle
4
Keine Ahnung, warum Sie hier herabgestimmt werden; Dies war genau das, was ich mir für meinen Anwendungsfall erhofft hatte: Eine bestimmte Version des Linux-Kernels von einer Version zu erhalten, die sie nicht als Release markieren konnten (scheint ein Problem für die RPi-Leute zu sein), ohne Herunterladen der gesamten Multi-Gigabyte-Geschichte von Linux. Übrigens hat es geklappt.
Fordi
1
--depth=1wird in der Antwort nicht erwähnt. Warum sollten Sie also sagen, dass diese Antwort funktioniert hat, wenn Sie weitere Dinge hinzugefügt haben, die hier nicht erwähnt werden? Ich bin froh, dass es für Sie geklappt hat, aber diese Antwort ist irreführend und beantwortet die Frage nicht einmal teilweise. Daher die Abstimmungen.
Emil Styrke
5
@Fordi: Nein. Wenn Sie diese Antwort wörtlich verwenden, erhalten Sie genau den gleichen Baum wie bei einer Vanille. Probieren Sie es git clone <url> <local_dir_name>einfach selbst aus. Der einzige Unterschied besteht darin, dass die Fernbedienung (gezeigt mit git remote) anstelle des üblichen Namens "Ursprung" eine kryptische sha1-Sequenz genannt wird. Mit anderen Worten, das <sha1-of-the-commit>in dieser Antwort erwähnte hat keinerlei Einfluss darauf, welche Revisionen vom Server abgerufen werden oder welcher Zweig ausgecheckt wird.
Emil Styrke
6
@ Fordi: Ich habe es gerade getan git clone -o 896066ee1cf4d653057dac4e952f49c96ad16fa7 https://github.com/torvalds/linux.git linux --depth=1. Dies gibt mir eine Überarbeitung 8a28d674und nicht, 896066ee wie Sie und diese Antwort behaupten.
Emil Styrke
4
Hervorheben, dass "Ursprung" nichts mit "Überarbeitung" zu tun hat und diese Antwort völlig falsch ist.
Eevee