it-swarm.com.de

Wie kann man nur eine einzige Datei aus einem Git-Repository spärlich auschecken?

Wie checke ich nur eine Datei aus einem Git Repo aus?

378
Arthur Ulfeldt

Ursprünglich erwähnte ich 2012 git archive (siehe Jared Forsyth s Antwort und Robert Knight s Antwort ), seit git1.7.9.5 (März 2012) , Paul Brannan 's Antwort :

git archive --format=tar --remote=Origin HEAD:path/to/directory -- filename | tar -O -xf -

Aber: 2013 war dies nicht mehr möglich für Remote-URLs von https://github.com .
Siehe die alte Seite " Kann ich ein Repository archivieren? "

Die aktuelle (2018) Seite " Informationen zum Archivieren von Inhalten und Daten auf GitHub " empfiehlt die Verwendung von Drittanbieterdiensten wie GHTorrent oder GH Archive .


So können Sie auch mit lokalen Kopien/Klonen umgehen:

Alternativ können Sie Folgendes tun, wenn Sie über eine lokale Kopie des nackten Repository verfügen, wie in diese Antwort erwähnt. _

git --no-pager --git-dir /path/to/bar/repo.git show branch:path/to/file >file

Oder Sie müssen zuerst das Repo klonen, dh Sie erhalten die vollständige Historie: - im .git-Repo - im Arbeitsbaum.

  • Aber dann können Sie SPÄRLICHE KASSE (wenn Sie Git1.7 + verwenden):
    • aktivieren Sie die Option zur spärlichen Kasse (git config core.sparsecheckout true).
    • hinzufügen, was in der .git/info/sparse-checkout-Datei angezeigt werden soll
    • lesen Sie den Arbeitsbaum erneut, um nur das anzuzeigen, was Sie benötigen 

Lesen Sie den Arbeitsbaum erneut:

$ git read-tree -m -u HEAD

Auf diese Weise erhalten Sie einen Arbeitsbaum mit genau dem, was Sie möchten (auch wenn es sich nur um eine Datei handelt).

227
VonC

Klonen Sie zunächst das Repo mit der Option -n, wodurch das Standard-Checkout aller Dateien unterdrückt wird, und mit der Option --depth 1, dh, es wird nur die neueste Revision jeder Datei abgerufen

git clone -n git://path/to/the_repo.git --depth 1

Dann checke einfach die gewünschte Datei aus:

cd the_repo
git checkout HEAD name_of_file
167
Nick Moore

Wenn Sie bereits eine Kopie des Git-Repos besitzen, können Sie immer eine Version einer Datei mit einem git log auschecken, um die Hash-ID herauszufinden (z. B. 3cdc61015724f9965575ba954c8cd4232c8b42e4) und dann einfach Folgendes einzugeben:

git checkout hash-id path-to-file

Hier ist ein aktuelles Beispiel:

git checkout 3cdc61015724f9965575ba954c8cd4232c8b42e4 /var/www/css/page.css
100
techexpert

Normalerweise ist es nicht möglich, nur eine Datei von git herunterzuladen, ohne das gesamte Repository wie in der ersten Antwort vorgeschlagen herunterzuladen .. __ Dies ist darauf zurückzuführen, dass Git Dateien nicht wie Sie denken (wie CVS/SVN) speichert, sondern sie basierend darauf generiert über die gesamte Geschichte des Projekts.

Es gibt jedoch einige Problemumgehungen für bestimmte Fälle. Siehe unten:

GitHub

Wenn sich diese Datei auf github.com befindet, versuchen Sie es beispielsweise:

wget https://raw.githubusercontent.com/user/project/master/README

GitWeb

Wenn Sie Git auf dem Server - GitWeb verwenden, können Sie es in Beispiel versuchen (ändern Sie es in den richtigen Pfad):

wget "http://example.com/gitweb/?p=example;a=blob_plain;f=README.txt;hb=HEAD"

GitWeb bei drupalcode.org

Beispiel:

wget "http://drupalcode.org/project/ads.git/blob_plain/refs/heads/master:/README.md"

googlesource.com

Es gibt eine undokumentierte Funktion, mit der Sie Base64-kodierte Versionen von RAW-Dateien herunterladen können:

curl "https://chromium.googlesource.com/chromium/src/net/+/master/http/transport_security_state_static.json?format=TEXT" | base64 --decode

Überprüfen Sie in anderen Fällen, ob Ihr Git-Repository Webschnittstellen verwendet.

Wenn keine Webschnittstelle verwendet wird, können Sie den Code an externe Dienste wie GitHub , Bitbucket , etc übertragen. und benutze es als Spiegel.

Wenn Sie wget nicht installiert haben, versuchen Sie alternativ curl -O (url).

45
kenorb

git checkout branch_or_version - Pfad/Datei

beispiel: git checkout HEAD -- main.c

36
36
Geoffrey Hale

Jetzt können wir! Da dies das erste Ergebnis bei Google ist, dachte ich, ich würde dieses auf den neuesten Stand bringen. Mit der Einführung von git 1.7.9.5 haben wir den Befehl git archive, mit dem Sie eine einzelne Datei von einem entfernten Host abrufen können.

git archive --remote=git://git.foo.com/project.git HEAD:path/in/repo filename | tar -x

Siehe die vollständige Antwort hier https://stackoverflow.com/a/5324532/290784

23
Jared Forsyth

Arbeiten in GIT 1.7.2.2

Zum Beispiel haben Sie eine entfernte some_remote mit Zweigen Zweig1 , Zweig32

um eine bestimmte Datei auszuchecken, rufen Sie folgende Befehle auf:

git checkout remote/branch path/to/file

als Beispiel wird es so etwas sein

git checkout some_remote/branch32 conf/en/myscript.conf
git checkout some_remote/branch1 conf/fr/load.wav

Dieser Checkout-Befehl kopiert die gesamte Dateistruktur "conf/en" und "conf/fr" in das aktuelle Verzeichnis, in dem Sie diese Befehle aufrufen.

21
anvk

Sehr einfach:

git checkout from-branch-name -- path/to/the/file/you/want

Der from-branch-name-Zweig wird dadurch nicht ausgecheckt. Sie bleiben in dem Zweig, in dem Sie sich gerade befinden, und nur diese einzelne Datei wird aus dem angegebenen Zweig ausgecheckt.

Hier ist der relevante Teil der Manpage für git-checkout

git checkout [-p|--patch] [<tree-ish>] [--] <pathspec>...
       When <paths> or --patch are given, git checkout does not switch
       branches. It updates the named paths in the working tree from the
       index file or from a named <tree-ish> (most often a commit). In
       this case, the -b and --track options are meaningless and giving
       either of them results in an error. The <tree-ish> argument can be
       used to specify a specific tree-ish (i.e. commit, tag or tree) to
       update the index for the given paths before updating the working
       tree.

Hat Tipp an Ariejan de Vroom, der mir das aus diesem Blogpost beigebracht hat.

12
broc.seib

Sie können es durch

git archive --format=tar --remote=Origin HEAD | tar xf -
git archive --format=tar --remote=Origin HEAD <file> | tar xf -
6
Fizer Khan

Zwei Varianten zu dem, was bereits gegeben wurde:

git archive --format=tar --remote=git://git.foo.com/project.git HEAD:path/to/directory filename | tar -O -xf -

und:

git archive --format=Zip --remote=git://git.foo.com/project.git HEAD:path/to/directory filename | funzip

Diese schreiben die Datei in die Standardausgabe.

5
Paul Brannan

Angenommen, der Dateiname lautet 123.txt. Dies funktioniert für mich:

git checkout --theirs  123.txt

Wenn sich die Datei in einem Verzeichnis A befindet, müssen Sie sie richtig angeben:

git checkout --theirs  "A/123.txt"
5
Joseph Wu

git clone --filter aus Git 2.19

Diese Option überspringt das Abrufen der meisten nicht benötigten Objekte vom Server:

git clone --depth 1 --no-checkout --filter=blob:none \
  "file://$(pwd)/server_repo" local_repo
cd local_repo
git checkout master -- mydir/myfile

Der Server sollte folgendermaßen konfiguriert werden:

git config --local uploadpack.allowfilter 1
git config --local uploadpack.allowanysha1inwant 1

Ab Version 2.19.0 gibt es keine Serverunterstützung, die jedoch bereits lokal getestet werden kann.

TODO: --filter=blob:none überspringt alle Blobs, ruft jedoch alle Baumobjekte ab. Bei einem normalen Repo sollte dies jedoch im Vergleich zu den Dateien selbst winzig sein, sodass dies bereits gut genug ist. Gefragt unter: https://www.spinics.net/lists/git/msg342006.html Devs antwortete, dass ein --filter=tree:0 in Arbeit ist, um dies zu tun.

Denken Sie daran, dass --depth 1 bereits --single-branch impliziert, siehe auch: Wie kann ich einen einzelnen Zweig in Git klonen?

file://$(path) ist erforderlich, um das git clone-Protokoll shenanigans zu überwinden: Wie kann ein lokales Git-Repository mit einem relativen Pfad flach geklont werden?

Das Format von --filter ist auf man git-rev-list dokumentiert. 

Das Git-Remote-Protokoll wurde erweitert, um diese Funktion zu unterstützen.

Dokumente im Git-Baum:

Teste es aus

#!/usr/bin/env bash
set -eu

list-objects() (
  git rev-list --all --objects
  echo "master commit SHA: $(git log -1 --format="%H")"
  echo "mybranch commit SHA: $(git log -1 --format="%H")"
  git ls-tree master
  git ls-tree mybranch | grep mybranch
  git ls-tree master~ | grep root
)

# Reproducibility.
export GIT_COMMITTER_NAME='a'
export GIT_COMMITTER_EMAIL='a'
export GIT_AUTHOR_NAME='a'
export GIT_AUTHOR_EMAIL='a'
export GIT_COMMITTER_DATE='2000-01-01T00:00:00+0000'
export GIT_AUTHOR_DATE='2000-01-01T00:00:00+0000'

rm -rf server_repo local_repo
mkdir server_repo
cd server_repo

# Create repo.
git init --quiet
git config --local uploadpack.allowfilter 1
git config --local uploadpack.allowanysha1inwant 1

# First commit.
# Directories present in all branches.
mkdir d1 d2
printf 'd1/a' > ./d1/a
printf 'd1/b' > ./d1/b
printf 'd2/a' > ./d2/a
printf 'd2/b' > ./d2/b
# Present only in root.
mkdir 'root'
printf 'root' > ./root/root
git add .
git commit -m 'root' --quiet

# Second commit only on master.
git rm --quiet -r ./root
mkdir 'master'
printf 'master' > ./master/master
git add .
git commit -m 'master commit' --quiet

# Second commit only on mybranch.
git checkout -b mybranch --quiet master~
git rm --quiet -r ./root
mkdir 'mybranch'
printf 'mybranch' > ./mybranch/mybranch
git add .
git commit -m 'mybranch commit' --quiet

echo "# List and identify all objects"
list-objects
echo

# Restore master.
git checkout --quiet master
cd ..

# Clone. Don't checkout for now, only .git/ dir.
git clone --depth 1 --quiet --no-checkout --filter=blob:none "file://$(pwd)/server_repo" local_repo
cd local_repo

# List missing objects from master.
echo "# Missing objects after --no-checkout"
git rev-list --all --quiet --objects --missing=print
echo

echo "# Git checkout fails without internet"
mv ../server_repo ../server_repo.off
! git checkout master
echo

echo "# Git checkout fetches the missing file from internet"
mv ../server_repo.off ../server_repo
git checkout master -- d1/a
echo

echo "# Missing objects after checking out d1/a"
git rev-list --all --quiet --objects --missing=print

GitHub Upstream .

Ausgabe in Git v2.19.0:

# List and identify all objects
c6fcdfaf2b1462f809aecdad83a186eeec00f9c1
fc5e97944480982cfc180a6d6634699921ee63ec
7251a83be9a03161acde7b71a8fda9be19f47128
62d67bce3c672fe2b9065f372726a11e57bade7e
b64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1
308150e8fddde043f3dbbb8573abb6af1df96e63 d1/a
f70a17f51b7b30fec48a32e4f19ac15e261fd1a4 d1/b
84de03c312dc741d0f2a66df7b2f168d823e122a d2
0975df9b39e23c15f63db194df7f45c76528bccb d2/a
41484c13520fcbb6e7243a26fdb1fc9405c08520 d2/b
7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master
8b25206ff90e9432f6f1a8600f87a7bd695a24af master/master
ef29f15c9a7c5417944cc09711b6a9ee51b01d89
19f7a4ca4a038aff89d803f017f76d2b66063043 mybranch
1b671b190e293aa091239b8b5e8c149411d00523 mybranch/mybranch
c3760bb1a0ece87cdbaf9a563c77a45e30a4e30e
a0234da53ec608b54813b4271fbf00ba5318b99f root
93ca1422a8da0a9effc465eccbcb17e23015542d root/root
master commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
mybranch commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
040000 tree b64bf435a3e54c5208a1b70b7bcb0fc627463a75    d1
040000 tree 84de03c312dc741d0f2a66df7b2f168d823e122a    d2
040000 tree 7d5230379e4652f1b1da7ed1e78e0b8253e03ba3    master
040000 tree 19f7a4ca4a038aff89d803f017f76d2b66063043    mybranch
040000 tree a0234da53ec608b54813b4271fbf00ba5318b99f    root

# Missing objects after --no-checkout
?f70a17f51b7b30fec48a32e4f19ac15e261fd1a4
?8b25206ff90e9432f6f1a8600f87a7bd695a24af
?41484c13520fcbb6e7243a26fdb1fc9405c08520
?0975df9b39e23c15f63db194df7f45c76528bccb
?308150e8fddde043f3dbbb8573abb6af1df96e63

# Git checkout fails without internet
fatal: '/home/ciro/bak/git/test-git-web-interface/other-test-repos/partial-clone.tmp/server_repo' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

# Git checkout fetches the missing directory from internet
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.

# Missing objects after checking out d1
?f70a17f51b7b30fec48a32e4f19ac15e261fd1a4
?8b25206ff90e9432f6f1a8600f87a7bd695a24af
?41484c13520fcbb6e7243a26fdb1fc9405c08520
?0975df9b39e23c15f63db194df7f45c76528bccb

Schlussfolgerungen: Alle Blobs außer d1/a fehlen. Z.B. f70a17f51b7b30fec48a32e4f19ac15e261fd1a4, dh d1/b, ist nach dem Auschecken von d1/ nicht verfügbar.

Beachten Sie, dass root/root und mybranch/mybranch auch fehlen, aber --depth 1 verbirgt dies aus der Liste der fehlenden Dateien. Wenn Sie --depth 1 entfernen, werden sie in der Liste der fehlenden Dateien angezeigt.

In git "checkout" Sie keine Dateien, bevor Sie sie aktualisieren - es scheint, dass Sie danach suchen.

Bei vielen Systemen wie Clearcase, CSV usw. müssen Sie eine Datei "auschecken", bevor Sie Änderungen daran vornehmen können. Git benötigt das nicht. Sie klonen ein Repository und nehmen dann Änderungen in Ihrer lokalen Repository-Kopie vor.

Sobald Sie Dateien aktualisiert haben, können Sie Folgendes tun:

git status

Um zu sehen, welche Dateien geändert wurden. Sie fügen diejenigen, die Sie festschreiben möchten, zuerst mit index hinzu (index ist wie eine Liste, die eingecheckt werden soll):

git add .

oder

git add blah.c

Dann zeigt Ihnen git status, welche Dateien geändert wurden und welche in index bereit sind, festgeschrieben oder eingecheckt zu werden.

Um Dateien an Ihre Repository-Kopie zu übergeben, gehen Sie folgendermaßen vor:

git commit -a -m "commit message here"

Siehe git website für Links zu Handbüchern und Handbüchern.

4
stefanB

Hier ist die komplette Lösung, um nur eine bestimmte Datei in das Git-Repository zu ziehen und zu pushen:

  1. Zuerst müssen Sie das Git-Repository mit einem speziellen Hinweis klonen - no checkout
git clone --no-checkout <git url>
  1. Der nächste Schritt, den Sie ausführen müssen, besteht darin, nicht bereitgestellte Dateien im Repository mit dem folgenden Befehl zu entfernen:
git reset
  1. Jetzt können Sie mit dem folgenden Befehl Dateien abrufen, die Sie ändern möchten:
git checkout Origin/master <path to file>
  1. Jetzt enthält der Repository-Ordner Dateien, die Sie sofort bearbeiten können. Nach der Bearbeitung müssen Sie eine einfache und vertraute Folge von Befehlen ausführen.
git add <path to file>
git commit -m <message text>
git Push

Siehe auch einen Link für zusätzliche Informationen.

2
ripreal

Wenn Sie eine bestimmte Datei von einem bestimmten Zweig von einem entfernten Git-Repository benötigen, lautet der Befehl:

git archive --remote=git://git.example.com/project.git refs/heads/mybranch path/to/myfile |tar xf -

Der Rest ergibt sich aus der Antwort von @ VonC:

Wenn Sie eine bestimmte Datei aus dem Hauptzweig benötigen, gilt Folgendes:

git archive --remote=git://git.example.com/project.git HEAD path/to/myfile |tar xf -

Wenn Sie eine bestimmte Datei von einem Tag benötigen, ist dies:

git archive --remote=git://git.example.com/project.git mytag path/to/myfile |tar xf -
1
Alex Harvey

Es klingt, als ob Sie versuchen, eine Idee aus der zentralen Versionskontrolle zu übernehmen, die von Natur aus nicht so ist - sie wird verteilt. Wenn Sie mit einem Git-Repository arbeiten möchten, klonen Sie es. Sie haben dann alle des Inhalts des Arbeitsbaums und alle der Historie (naja, zumindest alles, was bis zur Spitze des aktuellen Zweigs führt), nicht nur eine einzelne Datei oder ein Snapshot von einem einzigen Commit.

 git clone /path/to/repo
 git clone git://url/of/repo
 git clone http://url/of/repo
1
Cascabel

Wenn Sie nur die Datei herunterladen müssen, müssen Sie nicht mit Git auschecken.

GitHub Mate ist viel einfacher zu tun, es ist eine Chrome-Erweiterung, mit der Sie auf das Dateisymbol klicken können, um es herunterzuladen. auch Open Source

0
Cam Song

Ich sehe nicht, was hier für mich funktioniert hat, also werde ich es hinzufügen, sollte sich jemand in meiner Situation befinden.

Meine Situation: Ich habe ein Remote-Repository mit vielleicht 10.000 Dateien und muss eine RPM-Datei für mein Linux-System erstellen. Der Build des RPM beinhaltet einen Git-Klon von allem. Alles, was ich brauche, ist eine Datei, um den RPM-Build zu starten. Ich kann den gesamten Quellbaum klonen, der das tut, was ich brauche, aber es dauert zusätzliche zwei Minuten, um all diese Dateien herunterzuladen, wenn alles, was ich brauche, eine ist. Ich habe versucht, die git-Archivoption zu verwenden, die besprochen wurde, und bekam "fatal: Der Vorgang wird vom Protokoll nicht unterstützt." Es scheint, dass ich eine Art Archivierungsoption auf dem Server aktivieren muss und mein Server von bürokratischen Schlägern gepflegt wird, die Spaß machen es ist schwierig, Dinge zu erledigen.

Was ich schließlich tat, war, dass ich in das Web-Interface für bitbucket ging und die Datei sah, die ich brauchte. Ich habe mit der rechten Maustaste auf den Link geklickt, um eine unformatierte Kopie der Datei herunterzuladen, und im daraufhin angezeigten Popup die Option "Verknüpfung kopieren" ausgewählt. Ich konnte die RAW-Datei nicht einfach herunterladen, weil ich Dinge automatisieren musste und ich keine Browser-Schnittstelle auf meinem Linux-Server habe.

Für die Diskussion ergab sich daraus die URL:

https://ourArchive.ourCompany.com/projects/ThisProject/repos/data/raw/foo/bar.spec?at=refs%2Fheads%2FTheBranchOfInterest

Ich konnte diese Datei nicht direkt aus dem Bitbucket-Repository herunterladen, da ich mich zuerst anmelden musste. Nach ein wenig Graben fand ich das funktioniert: Unter Linux:

echo "myUser:myPass123"| base64
bXlVc2VyOm15UGFzczEyMwo=

curl -H 'Authorization: Basic bXlVc2VyOm15UGFzczEyMwo=' 'https://ourArchive.ourCompany.com/projects/ThisProject/repos/data/raw/foo/bar.spec?at=refs%2Fheads%2FTheBranchOfInterest' > bar.spec

Diese Kombination erlaubte mir, die einzige Datei herunterzuladen, die ich brauchte, um alles andere zu bauen.

0
user1683793

Ich füge diese Antwort als Alternative zu einem formellen Checkout oder einer ähnlichen lokalen Operation hinzu. Vorausgesetzt, Sie haben Zugriff auf das Web-Interface Ihres Git-Providers, können Sie möglicherweise jede Datei direkt zu einem bestimmten Commit anzeigen. Auf GitHub können Sie beispielsweise Folgendes verwenden:

https://github.com/hubotio/hubot/blob/ed25584f/src/adapter.coffee

Hier ist ed25584f die ersten 8 Zeichen des SHA-1-Hash des betreffenden Commits, gefolgt vom Pfad zur Quelldatei.

Gleichermaßen können wir bei Bitbucket versuchen:

https://bitbucket.org/cofarrell/stash-browse-code-plugin/src/06befe08

In diesem Fall setzen wir den Commit-Hash am Ende der Quell-URL.

0
Tim Biegeleisen