Comment extraire un seul fichier d'un dépôt git?
Comment extraire un seul fichier d'un dépôt git?
Réponses:
A l' origine, je l' ai mentionné en 2012 git archive
(voir Jared Forsyth est réponse et Robert Knight 's réponse ), depuis git1.7.9.5 (Mars 2012) , Paul Brannan de réponse :
git archive --format=tar --remote=origin HEAD:path/to/directory -- filename | tar -O -xf -
Mais: en 2013, cela n'était plus possible pour les URL https://github.com distantes .
Voir l'ancienne page " Puis-je archiver un référentiel? "
La page actuelle (2018) « À propos de l'archivage du contenu et des données sur GitHub » recommande d'utiliser des services tiers tels que GHTorrent ou GH Archive .
Vous pouvez donc également gérer les copies / clones locaux:
Vous pouvez également effectuer les opérations suivantes si vous disposez d'une copie locale du référentiel nu, comme indiqué dans cette réponse ,
git --no-pager --git-dir /path/to/bar/repo.git show branch:path/to/file >file
Ou vous devez d'abord cloner le dépôt, ce qui signifie que vous obtenez l'historique complet: - dans le dépôt .git - dans l'arborescence de travail.
git config core.sparsecheckout true
).git/info/sparse-checkout
fichierPour relire l'arborescence de travail:
$ git read-tree -m -u HEAD
De cette façon, vous vous retrouvez avec un arbre de travail comprenant précisément ce que vous voulez (même s'il ne s'agit que d'un seul fichier)
Richard Gomes pointe ( dans les commentaires ) sur " Comment puis-je cloner, récupérer ou extraire une extraction d'un répertoire unique ou d'une liste de répertoires à partir du référentiel git? "
Une fonction bash qui évite de télécharger l'historique, qui récupère une seule branche et qui récupère la liste des fichiers ou répertoires dont vous avez besoin.
git archive
maintenant.
Commencez par cloner le référentiel avec l'option -n, qui supprime l'extraction par défaut de tous les fichiers, et l'option --depth 1, ce qui signifie qu'il n'obtient que la révision la plus récente de chaque fichier.
git clone -n git://path/to/the_repo.git --depth 1
Ensuite, vérifiez uniquement le fichier que vous souhaitez comme ceci:
cd the_repo
git checkout HEAD name_of_file
-n
l'arbre de travail et l'index finissant en synchronisation. Autrement dit, tout le contenu apparaît comme supprimé. Vous devez soit git reset HEAD
ou git checkout HEAD file
. Il est également très difficile de travailler avec le référentiel à ce stade, sauf si vous comprenez vraiment comment git fonctionne.
rm -rf .git
au script de NickMoore, nettoierait toutes les traces du repo cloné et apaiserait peut-être Jefromi quant à un repo difficile à utiliser. Cela me rend très utile pour plusieurs applications, comme mon défi aujourd'hui de construire un hook post-réception pour mettre à jour automatiquement la version d'un autre hook post-réception.
git
pas la meilleure pour ce genre de travail). Cette réponse est également valable pour cette question , ou cette autre populaire , et bien d'autres: passez name_of_file
à name_of_folder
. De nos jours (2014s), Git propose des sous - modules aux propriétaires de référentiels et certains sont conviviaux pour les utilisateurs de référentiels.
Si vous avez déjà une copie du dépôt git, vous pouvez toujours extraire une version d'un fichier à l'aide de a git log
pour connaître le hash-id (par exemple 3cdc61015724f9965575ba954c8cd4232c8b42e4), puis vous tapez simplement:
git checkout hash-id path-to-file
Voici un exemple réel:
git checkout 3cdc61015724f9965575ba954c8cd4232c8b42e4 /var/www/css/page.css
path-to-file
s'agit d'un répertoire et que current HEAD
contient certains fichiers alors que ce target
n'est pas le cas (ou vice versa), cela ne mettra pas correctement à jour le fichier. Existe-t-il un moyen de gérer?
Normalement, il n'est pas possible de télécharger un seul fichier git
sans télécharger l'intégralité du référentiel comme suggéré dans la première réponse. C'est parce que Git ne stocke pas les fichiers comme vous le pensez (comme le font CVS / SVN), mais il les génère en fonction de l'historique complet du projet.
Mais il existe des solutions de contournement pour des cas spécifiques. Les exemples ci - dessous avec des espaces réservés pour 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
Si vous utilisez Git sur le serveur - GitWeb , alors vous pouvez essayer dans l'exemple (le changer dans le bon chemin):
wget "http://example.com/gitweb/?p=example;a=blob_plain;f=README.txt;hb=HEAD"
GitWeb sur drupalcode.org
Exemple:
wget "http://drupalcode.org/project/ads.git/blob_plain/refs/heads/master:/README.md"
googlesource.com
Il existe une fonctionnalité non documentée qui vous permet de télécharger des versions encodées en base64 de fichiers bruts:
curl "https://chromium.googlesource.com/chromium/src/net/+/master/http/transport_security_state_static.json?format=TEXT" | base64 --decode
Dans d'autres cas, vérifiez si votre référentiel Git utilise des interfaces Web.
Si elle ne l' utilise une interface Web, vous pouvez envisager de pousser votre code à des services externes tels que GitHub , Bitbucket , etc . et l'utiliser comme miroir.
Si vous ne l'avez pas wget
installé, essayez curl -O (url)
alternativement.
wget
réponse brillante et les retours de simplicité, ainsi que le bonheur. Merci mec.
git checkout branch_or_version - chemin / fichier
exemple: git checkout HEAD -- main.c
git checkout -- <filename>
Réf: https://git-scm.com/docs/git-checkout
Dup: Annuler les modifications de copie de travail d'un fichier dans Git?
git-checkout
.
Maintenant nous pouvons! Comme il s'agit du premier résultat sur Google, j'ai pensé mettre à jour ce dernier. Avec l'avènement de git 1.7.9.5, nous avons la git archive
commande qui vous permettra de récupérer un seul fichier depuis un hôte distant.
git archive --remote=git://git.foo.com/project.git HEAD:path/in/repo filename | tar -x
Voir la réponse complète ici https://stackoverflow.com/a/5324532/290784
github.com
HEAD
ou master
non HEAD:directory
.
git archive --remote=git@bitbucket.org:user/repo branch:path/to file | tar -x
Travailler dans GIT 1.7.2.2
Par exemple, vous avez une télécommande some_remote avec des branches branch1 , branch32
donc pour extraire un fichier spécifique, vous appelez ces commandes:
git checkout remote/branch path/to/file
à titre d'exemple, ce sera quelque chose comme ça
git checkout some_remote/branch32 conf/en/myscript.conf
git checkout some_remote/branch1 conf/fr/load.wav
Cette commande d'extraction copiera la structure de fichier entière conf / en et conf / fr dans le répertoire courant où vous appelez ces commandes (bien sûr, je suppose que vous avez exécuté git init à un moment donné auparavant)
git fetch some_remote
avant, non?
Très simple:
git checkout from-branch-name -- path/to/the/file/you/want
Cela ne vérifie pas la from-branch-name
succursale. Vous resterez sur la branche sur laquelle vous vous trouvez et seul ce fichier sera extrait de la branche spécifiée.
Voici la partie pertinente de la page de manuel pour 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.
Pointe du chapeau à Ariejan de Vroom qui m'a appris cela à partir de ce blog .
git clone --filter
de Git 2.19
Cette option sautera en fait la récupération de la plupart des objets inutiles du serveur:
git clone --depth 1 --no-checkout --filter=blob:none \
"file://$(pwd)/server_repo" local_repo
cd local_repo
git checkout master -- mydir/myfile
Le serveur doit être configuré avec:
git config --local uploadpack.allowfilter 1
git config --local uploadpack.allowanysha1inwant 1
Il n'y a pas de support serveur à partir de la v2.19.0, mais il peut déjà être testé localement.
TODO: --filter=blob:none
ignore tous les blobs, mais récupère toujours tous les objets d'arbre. Mais sur un dépôt normal, cela devrait être minuscule par rapport aux fichiers eux-mêmes, donc c'est déjà assez bon. Demandé à: https://www.spinics.net/lists/git/msg342006.html Devs a répondu qu'un --filter=tree:0
était en train de le faire.
N'oubliez pas que cela --depth 1
implique déjà --single-branch
, voir aussi: Comment cloner une seule branche dans Git?
file://$(path)
est nécessaire pour surmonter git clone
les manigances du protocole: Comment cloner superficiellement un dépôt git local avec un chemin relatif?
Le format de --filter
est documenté sur man git-rev-list
.
Une extension a été apportée au protocole distant Git pour prendre en charge cette fonctionnalité.
Documents sur l'arbre Git:
Testez-le
#!/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
Sortie dans 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
Conclusions: tous les blobs sauf d1/a
sont manquants. Par exemple f70a17f51b7b30fec48a32e4f19ac15e261fd1a4
, ce qui n'est d1/b
pas le cas après le paiement d1/
.
Notez que root/root
et mybranch/mybranch
sont également manquants, mais les --depth 1
masquent dans la liste des fichiers manquants. Si vous supprimez --depth 1
, ils apparaissent sur la liste des fichiers manquants.
Vous pouvez le faire en
git archive --format=tar --remote=origin HEAD | tar xf -
git archive --format=tar --remote=origin HEAD <file> | tar xf -
Deux variantes de ce qui a déjà été proposé:
git archive --format=tar --remote=git://git.foo.com/project.git HEAD:path/to/directory filename | tar -O -xf -
et:
git archive --format=zip --remote=git://git.foo.com/project.git HEAD:path/to/directory filename | funzip
Ceux-ci écrivent le fichier sur la sortie standard.
Dans git, vous ne récupérez pas les fichiers avant de les mettre à jour - il semble que c'est ce que vous recherchez.
De nombreux systèmes comme clearcase, csv et ainsi de suite vous obligent à «extraire» un fichier avant de pouvoir y apporter des modifications. Git ne l'exige pas. Vous clonez un référentiel, puis apportez des modifications dans votre copie locale du référentiel.
Une fois que vous avez mis à jour les fichiers, vous pouvez faire:
git status
Pour voir quels fichiers ont été modifiés. Vous ajoutez ceux avec lesquels vous souhaitez vous engager en index
premier ( index
c'est comme une liste à archiver):
git add .
ou
git add blah.c
Ensuite, do git status
vous montrera quels fichiers ont été modifiés et lesquels sont index
prêts à être validés ou archivés.
Pour valider des fichiers dans votre copie du référentiel, procédez comme suit:
git commit -a -m "commit message here"
Consultez le git
site Web pour des liens vers des manuels et des guides.
git format-patch
pour créer un patch pour la soumission ( git format-patch -1
créera un patch pour votre dernier commit).
Voici la solution complète pour extraire et pousser uniquement un fichier particulier à l'intérieur du référentiel git:
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
Voir également un lien pour des informations supplémentaires.
Il semble que vous essayez de transmettre une idée du contrôle de version centralisé, ce qui n'est pas le cas par nature - il est distribué. Si vous souhaitez travailler avec un référentiel git, vous le clonez. Vous avez alors tout le contenu de l'arborescence de travail et tout l'historique (enfin, au moins tout ce qui mène à la pointe de la branche actuelle), pas seulement un seul fichier ou un instantané à partir d'un seul commit.
git clone /path/to/repo
git clone git://url/of/repo
git clone http://url/of/repo
Si vous avez besoin d'un fichier spécifique d'une branche spécifique d'un référentiel Git distant, la commande est:
git archive --remote=git://git.example.com/project.git refs/heads/mybranch path/to/myfile |tar xf -
Le reste peut être dérivé de la réponse de @ VonC:
Si vous avez besoin d'un fichier spécifique de la branche master c'est:
git archive --remote=git://git.example.com/project.git HEAD path/to/myfile |tar xf -
Si vous avez besoin d'un fichier spécifique à partir d'une balise, c'est:
git archive --remote=git://git.example.com/project.git mytag path/to/myfile |tar xf -
Je ne vois pas ce qui a fonctionné pour moi énuméré ici, donc je l'inclurai si quelqu'un se trouve dans ma situation.
Ma situation, j'ai un référentiel distant de peut-être 10 000 fichiers et j'ai besoin de créer un fichier RPM pour mon système Linux. La construction du RPM inclut un clone git de tout. Tout ce dont j'ai besoin, c'est d'un fichier pour démarrer la génération RPM. Je peux cloner l'arborescence source entière qui fait ce dont j'ai besoin, mais cela prend deux minutes supplémentaires pour télécharger tous ces fichiers lorsque tout ce dont j'ai besoin est un. J'ai essayé d'utiliser l'option d'archivage git discutée et j'ai eu «fatal: opération non prise en charge par le protocole». Il semble que je doive activer une sorte d’option d’archivage sur le serveur et mon serveur est entretenu par des voyous bureaucratiques qui semblent apprécier de compliquer les choses.
Ce que j'ai finalement fait, c'est que je suis entré dans l'interface Web de bitbucket et j'ai consulté le fichier dont j'avais besoin. J'ai fait un clic droit sur le lien pour télécharger une copie brute du fichier et sélectionné "copier le raccourci" dans la fenêtre contextuelle résultante. Je ne pouvais pas simplement télécharger le fichier brut car j'avais besoin d'automatiser les choses et je n'ai pas d'interface de navigateur sur mon serveur Linux.
Pour des raisons de discussion, cela a abouti à l'URL:
https://ourArchive.ourCompany.com/projects/ThisProject/repos/data/raw/foo/bar.spec?at=refs%2Fheads%2FTheBranchOfInterest
Je n'ai pas pu télécharger directement ce fichier à partir du référentiel bitbucket car je devais d'abord me connecter. Après avoir creusé un peu, j'ai trouvé que cela fonctionnait: Sous 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
Cette combinaison m'a permis de télécharger le fichier dont j'avais besoin pour construire tout le reste.
J'ajoute cette réponse comme alternative à la vérification formelle ou à une opération locale similaire. En supposant que vous ayez accès à l'interface Web de votre fournisseur Git, vous pourrez peut-être visualiser directement n'importe quel fichier à un commit donné. Par exemple, sur GitHub, vous pouvez utiliser quelque chose comme:
https://github.com/hubotio/hubot/blob/ed25584f/src/adapter.coffee
Voici ed25584f
les 8 premiers caractères du hachage SHA-1 de la validation d'intérêt, suivis du chemin d'accès au fichier source.
De même, sur Bitbucket, nous pouvons essayer:
https://bitbucket.org/cofarrell/stash-browse-code-plugin/src/06befe08
Dans ce cas, nous plaçons le hachage de validation à la fin de l'URL source.
Si vous avez seulement besoin de télécharger le fichier, pas besoin de vérifier avec Git.
GitHub Mate est beaucoup plus facile à faire, c'est une extension Chrome, vous permet de cliquer sur l'icône du fichier pour le télécharger. également open source
git
! =github
Si vous avez modifié une version locale d'un fichier et que vous souhaitez revenir à la version d'origine conservée sur le serveur central, cela peut être facilement réalisé à l'aide de Git Extensions .
Facile!