Wie checke ich nur eine Datei aus einem Git-Repo aus?
Wie checke ich nur eine Datei aus einem Git-Repo aus?
Antworten:
Ursprünglich habe ich erwähnt , im Jahr 2012 git archive
(siehe Jared Forsyth 's Antwort und Robert Knight ' s Antwort ), da 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 für Remote-URLs von https://github.com nicht mehr möglich .
Siehe die alte Seite " Kann ich ein Repository archivieren? "
Auf der aktuellen Seite (2018) " Informationen zum Archivieren von Inhalten und Daten auf GitHub " wird die Verwendung von Diensten von Drittanbietern wie GHTorrent oder GH Archive empfohlen .
Sie können also auch mit lokalen Kopien / Klonen umgehen:
Sie können alternativ Folgendes tun, wenn Sie eine lokale Kopie des nackten Repositorys haben, wie in dieser 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, was bedeutet, dass Sie den vollständigen Verlauf erhalten: - im .git-Repo - im Arbeitsbaum.
git config core.sparsecheckout true
).git/info/sparse-checkout
Datei sehen möchtenSo lesen Sie den Arbeitsbaum erneut:
$ git read-tree -m -u HEAD
Auf diese Weise erhalten Sie einen Arbeitsbaum, der genau das enthält, was Sie möchten (auch wenn es sich nur um eine Datei handelt).
Richard Gomes verweist ( in den Kommentaren ) auf " Wie kann ich ein einzelnes Verzeichnis oder eine Liste von Verzeichnissen aus dem Git-Repository klonen, abrufen oder spärlich auschecken? "
Eine Bash-Funktion, die das Herunterladen des Verlaufs vermeidet, einen einzelnen Zweig abruft und eine Liste der benötigten Dateien oder Verzeichnisse abruft.
git archive
jetzt verwenden.
Klonen Sie zuerst das Repo mit der Option -n, die das standardmäßige Auschecken aller Dateien unterdrückt, und der Option --depth 1, dh, es wird nur die neueste Version jeder Datei abgerufen
git clone -n git://path/to/the_repo.git --depth 1
Dann schauen Sie sich einfach die gewünschte Datei an:
cd the_repo
git checkout HEAD name_of_file
-n
der Arbeitsbaum und der Index synchron sind. Das heißt, alle Inhalte werden als gelöscht angezeigt. Du musst entweder git reset HEAD
oder git checkout HEAD file
. Es ist zu diesem Zeitpunkt auch sehr schwierig, mit dem Repository zu arbeiten, es sei denn, Sie verstehen wirklich, wie Git funktioniert.
rm -rf .git
zu NickMoores Skript hinzufügt , würde dies alle Spuren des geklonten Repos bereinigen und vielleicht Jefromis Besorgnis über ein schwer zu verwendendes Repo zerstreuen. Das macht es für mich für verschiedene Anwendungen sehr nützlich, wie meine heutige Herausforderung, einen Post-Receive-Hook zu erstellen, um die Version eines anderen Post-Receive-Hooks automatisch zu aktualisieren.
git
nicht die beste für diese Art von Arbeit). Diese Antwort gilt auch für diese oder diese andere beliebte Frage und viele andere: Ändern Sie name_of_file
zu name_of_folder
. Git bietet heutzutage (2014er Jahre) Submodule für Repo-Besitzer an, die für Repo-Benutzer einige por-freundliche bieten.
Wenn Sie bereits eine Kopie des Git-Repos haben, können Sie jederzeit eine Version einer Datei mit a git log
auschecken, um die Hash-ID herauszufinden (z. B. 3cdc61015724f9965575ba954c8cd4232c8b42e4), und dann einfach Folgendes eingeben:
git checkout hash-id path-to-file
Hier ist ein aktuelles Beispiel:
git checkout 3cdc61015724f9965575ba954c8cd4232c8b42e4 /var/www/css/page.css
path-to-file
es sich jedoch um ein Verzeichnis handelt und current HEAD
eine bestimmte Datei enthält, während target
dies nicht der Fall ist (oder umgekehrt), wird die Datei dadurch nicht korrekt aktualisiert. Gibt es eine Möglichkeit, damit umzugehen?
Normalerweise ist es nicht möglich, nur eine Datei git
herunterzuladen, ohne das gesamte Repository herunterzuladen, wie in der ersten Antwort vorgeschlagen. Dies liegt daran, dass Git Dateien nicht so speichert, wie Sie denken (wie CVS / SVN), sondern sie basierend auf dem gesamten Verlauf des Projekts generiert.
Es gibt jedoch einige Problemumgehungen für bestimmte Fälle. Beispiele unten mit Platzhalter für user
, project
, branch
, filename
.
GitHub
wget https://raw.githubusercontent.com/user/project/branch/filename
GitLab
wget https://gitlab.com/user/project/raw/branch/filename
GitWeb
Wenn Sie Git auf dem Server - GitWeb verwenden , können Sie es in einem 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-codierte Versionen von Rohdateien herunterladen können:
curl "https://chromium.googlesource.com/chromium/src/net/+/master/http/transport_security_state_static.json?format=TEXT" | base64 --decode
In anderen Fällen überprüfen Sie, ob Ihr Git-Repository Webschnittstellen verwendet.
Wenn es keine Web - Oberfläche verwenden, können Sie prüfen , um Ihren Code zu externen Diensten schieben wie GitHub , Bitbucket , etc . und benutze es als Spiegel.
Wenn Sie nicht wget
installiert haben, versuchen Sie es curl -O (url)
alternativ.
wget
Antwort. Die Einfachheit kehrt zusammen mit dem Glück zurück. Danke, Mann.
git checkout branch_or_version - Pfad / Datei
Beispiel: git checkout HEAD -- main.c
git checkout -- <filename>
Ref: https://git-scm.com/docs/git-checkout
Dup: Arbeitskopienänderungen einer Datei in Git rückgängig machen?
git-checkout
.
Jetzt können wir! Da dies das erste Ergebnis bei Google ist, dachte ich, ich würde es auf den neuesten Stand bringen. Mit dem Aufkommen von git 1.7.9.5 haben wir den git archive
Befehl, mit dem Sie eine einzelne Datei von einem Remote-Host abrufen können.
git archive --remote=git://git.foo.com/project.git HEAD:path/in/repo filename | tar -x
Die vollständige Antwort finden Sie hier https://stackoverflow.com/a/5324532/290784
github.com
HEAD
oder master
nicht HEAD:directory
.
git archive --remote=git@bitbucket.org:user/repo branch:path/to file | tar -x
Arbeiten in GIT 1.7.2.2
Zum Beispiel haben Sie eine entfernte some_remote mit Zweigen branch1 , branch32
Um eine bestimmte Datei auszuchecken, rufen Sie die folgenden 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 (natürlich gehe ich davon aus, dass Sie git init irgendwann zuvor ausgeführt haben).
git fetch some_remote
vorher rennen , nicht wahr?
Sehr einfach:
git checkout from-branch-name -- path/to/the/file/you/want
Dadurch wird der from-branch-name
Zweig nicht ausgecheckt . Sie bleiben in jedem Zweig, in dem Sie sich 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.
Hutspitze an Ariejan de Vroom, der mir dies aus diesem Blog-Beitrag beigebracht hat .
git clone --filter
ab 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 konfiguriert sein mit:
git config --local uploadpack.allowfilter 1
git config --local uploadpack.allowanysha1inwant 1
Ab Version 2.19.0 gibt es keine Serverunterstützung, diese kann jedoch bereits lokal getestet werden.
TODO: --filter=blob:none
Überspringt alle Blobs, ruft aber trotzdem 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 Entwickler antworteten --filter=tree:0
, dass dies in Arbeit ist.
Denken Sie daran, dass dies --depth 1
bereits impliziert --single-branch
, siehe auch: Wie klone ich einen einzelnen Zweig in Git?
file://$(path)
ist erforderlich, um git clone
Protokoll-Spielereien zu überwinden : Wie kann ein lokales Git-Repository mit einem relativen Pfad flach geklont werden ?
Das Format von --filter
ist am dokumentiert man git-rev-list
.
Das Git-Remote-Protokoll wurde erweitert, um diese Funktion zu unterstützen.
Dokumente auf Git-Baum:
Probieren Sie 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
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. ZB f70a17f51b7b30fec48a32e4f19ac15e261fd1a4
das heißt d1/b
, ist nach dem Auschecken nicht dad1/
.
Beachten Sie, dass root/root
und mybranch/mybranch
auch fehlen, --depth 1
verbirgt dies jedoch in der Liste der fehlenden Dateien. Wenn Sie entfernen --depth 1
, werden sie in der Liste der fehlenden Dateien angezeigt.
Sie können es tun, indem Sie
git archive --format=tar --remote=origin HEAD | tar xf -
git archive --format=tar --remote=origin HEAD <file> | tar xf -
Zwei Varianten dessen, 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.
In git "checken" Sie Dateien nicht aus, bevor Sie sie aktualisieren - es scheint, als ob 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 dies nicht. Sie klonen ein Repository und nehmen dann Änderungen an Ihrer lokalen Kopie des Repositorys vor.
Sobald Sie die Dateien aktualisiert haben, können Sie Folgendes tun:
git status
Um zu sehen, welche Dateien geändert wurden. Sie fügen diejenigen hinzu, für die Sie sich index
zuerst festlegen möchten (entspricht index
einer einzucheckenden Liste):
git add .
oder
git add blah.c
Dann git status
zeigt Ihnen do , welche Dateien geändert wurden und welche index
zum Festschreiben oder Einchecken bereit sind .
Um Dateien in Ihre Kopie des Repositorys zu übertragen, gehen Sie wie folgt vor:
git commit -a -m "commit message here"
Auf der git
Website finden Sie Links zu Handbüchern und Anleitungen.
git format-patch
, um einen Patch für die Übermittlung zu erstellen ( git format-patch -1
erstellt einen Patch) nur für Ihr letztes Commit).
Hier ist die vollständige Lösung zum Abrufen und Verschieben nur einer bestimmten Datei im Git-Repository:
git clone --no-checkout <git url>
git reset
git checkout origin/master <path to file>
git add <path to file>
git commit -m <message text>
git push
Siehe auch einen Link für einige zusätzliche Informationen.
Es hört sich so an, als würden Sie versuchen, eine Idee aus der zentralen Versionskontrolle zu übernehmen, was Git von Natur aus nicht ist - es ist verteilt. Wenn Sie mit einem Git-Repository arbeiten möchten, klonen Sie es. Sie haben dann den gesamten Inhalt des Arbeitsbaums und den gesamten Verlauf (zumindest alles, was bis zur Spitze des aktuellen Zweigs führt), nicht nur eine einzelne Datei oder einen Snapshot aus einem einzelnen Commit.
git clone /path/to/repo
git clone git://url/of/repo
git clone http://url/of/repo
Wenn Sie eine bestimmte Datei aus einem bestimmten Zweig eines Remote-Git-Repositorys benötigen, lautet der Befehl:
git archive --remote=git://git.example.com/project.git refs/heads/mybranch path/to/myfile |tar xf -
Der Rest kann aus der Antwort von @ VonC abgeleitet werden:
Wenn Sie eine bestimmte Datei aus dem Hauptzweig benötigen, ist dies:
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 -
Ich sehe nicht, was für mich funktioniert hat, also werde ich es aufnehmen, falls sich jemand in meiner Situation befindet.
In meiner Situation habe ich ein Remote-Repository mit möglicherweise 10.000 Dateien und muss eine RPM-Datei für mein Linux-System erstellen. Der Build des RPM enthält einen Git-Klon von allem. Ich brauche nur 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 alle diese Dateien herunterzuladen, wenn ich nur eine brauche. Ich habe versucht, die besprochene Git-Archivierungsoption zu verwenden, und wurde "fatal: Operation wird vom Protokoll nicht unterstützt". Es scheint, dass ich eine Art Archivierungsoption auf dem Server aktivieren muss, und mein Server wird von bürokratischen Schlägern gewartet, die es anscheinend genießen, es schwierig zu machen, Dinge zu erledigen.
Was ich schließlich tat, war, dass ich in das Webinterface für Bitbucket ging und die eine Datei ansah, die ich brauchte. Ich habe mit der rechten Maustaste auf den Link geklickt, um eine Rohkopie der Datei herunterzuladen, und im resultierenden Popup die Option "Verknüpfung zum Kopieren" ausgewählt. Ich konnte die Rohdatei nicht einfach herunterladen, da ich die Dinge automatisieren musste und auf meinem Linux-Server keine Browser-Oberfläche habe.
Aus Gründen der 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 einigem Graben fand ich, dass dies funktionierte: 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
Mit dieser Kombination konnte ich die eine Datei herunterladen, die ich zum Erstellen aller anderen Dateien benötigte.
Ich füge diese Antwort als Alternative zu einer formellen Kaufabwicklung oder einer ähnlichen lokalen Operation hinzu. Angenommen, Sie haben Zugriff auf die Weboberfläche Ihres Git-Anbieters, können Sie möglicherweise jede Datei bei einem bestimmten gewünschten Commit direkt anzeigen. Auf GitHub können Sie beispielsweise Folgendes verwenden:
https://github.com/hubotio/hubot/blob/ed25584f/src/adapter.coffee
Hier ed25584f
sind die ersten 8 Zeichen aus dem SHA-1-Hash des Commits von Interesse, gefolgt vom Pfad zur Quelldatei.
Ähnlich können wir auf Bitbucket versuchen:
https://bitbucket.org/cofarrell/stash-browse-code-plugin/src/06befe08
In diesem Fall platzieren wir den Commit-Hash am Ende der Quell-URL.
Wenn Sie nur die Datei herunterladen müssen, müssen Sie nicht mit Git auschecken.
GitHub Mate ist viel einfacher, es ist eine Chrome-Erweiterung, mit der Sie auf das Dateisymbol klicken können, um es herunterzuladen. auch Open Source
git
! =github
Wenn Sie eine lokale Version einer Datei bearbeitet haben und zur ursprünglichen Version zurückkehren möchten, die auf dem zentralen Server verwaltet wird, können Sie dies problemlos mit Git Extensions erreichen .
Einfach!