git pull sans être dans un répertoire git

308

Disons que j'ai un répertoire /X/Y, qui est un référentiel git. Est-il possible d'appeler d'une manière ou d'une autre une commande comme git pullde l'intérieur /X, mais en ciblant le /X/Yrépertoire?

EDIT: Je suppose que je me demandais précisément: est-il possible de le faire en utilisant la commande a git, mais sans avoir à changer de répertoire?

REMARQUE: j'ai accepté la réponse de VonC car elle est beaucoup plus élégante que les options précédentes. Pour les personnes utilisant Git plus tôt que 1.8.5, veuillez voir la réponse de bstpierre ci-dessous .

Gavin Anderegg
la source
2
Je voudrais ajouter que lorsque vous utilisez git-pull dans un hook, cela ne fonctionnera que si vous désactivez GIT_DIR. Pertinent.
zpmorgan
À partir de git 1.8.5 (Q4 2013), vous pourrez "utiliser une commande git, mais sans avoir à changer de répertoire". Voir ma réponse ci
VonC

Réponses:

453

À partir de git 1.8.5 (Q4 2013) , vous pourrez "utiliser une commande Git, mais sans avoir à changer de répertoire".

Tout comme " make -C <directory>", " git -C <directory> ..." dit à Git d'y aller avant de faire autre chose .

Voir commit 44e1e4 de Nazri Ramliy :

Il faut plus de touches pour appeler la commande Git dans un répertoire différent sans quitter le répertoire courant:

  1. (cd ~/foo && git status)
    git --git-dir=~/foo/.git --work-tree=~/foo status
    GIT_DIR=~/foo/.git GIT_WORK_TREE=~/foo git status
  2. (cd ../..; git grep foo)
  3. for d in d1 d2 d3; do (cd $d && git svn rebase); done

Les méthodes présentées ci-dessus sont acceptables pour les scripts mais sont trop lourdes pour des appels rapides en ligne de commande.

Avec cette nouvelle option, ce qui précède peut être fait avec moins de frappes:

  1. git -C ~/foo status
  2. git -C ../.. grep foo
  3. for d in d1 d2 d3; do git -C $d svn rebase; done

Depuis Git 2.3.4 (mars 2015), et commit 6a536e2 par Karthik Nayak ( KarthikNayak) , gittraitera " git -C '<path>'" comme un no-op quand il <path>est vide.

' git -C ""' meurt inutilement avec l'erreur " Cannot change to ''", alors que le shell traite le cd "" 'comme un no-op.
En prenant le comportement du shell comme précédent, apprenez également gità traiter -C "" 'comme un no-op.


4 ans plus tard, Git 2.23 (Q3 2019) documente que ' git -C ""' fonctionne et ne change pas de répertoire

Il se comporte ainsi depuis 6a536e2 ( git: traiter " git -C '<path>'" comme un no-op lorsqu'il <path>est vide, 2015-03-06, Git v2.3.4).

Cela signifie que la documentation comprend maintenant (enfin):

Si ' <path>' est présent mais vide, par exemple -C "", le répertoire de travail actuel reste inchangé.


Vous pouvez voir git -Cutilisé avec Git 2.26 (Q1 2020), à titre d'exemple.

Voir commit b441717 , commit 9291e63 , commit 5236fce , commit 10812c2 , commit 62d58cd , commit b87b02c , commit 9b92070 , commit 3595d10 , commit f511bc0 , commit f6041ab , commit f46c243 , commit 99c049b , commit 3738439 , commit 77172490 , commit b8af ) par Denton Liu ( Denton-L) .
(Fusionné par Junio ​​C Hamano - gitster- en commit 381e8e9 , 05 fév 2020)

t1507: en ligne full_name()

Signé par: Denton Liu

Avant, nous courions test_must_fail full_name. Cependant, test_must_failne doit être utilisé que sur les commandes git.
Inline full_name()afin que nous puissions utiliser directement test_must_failla gitcommande.

Lorsqu'elle a full_name()été introduite dans 28fb84382b ("Introduce <branch>@{upstream}notation", 2009-09-10, Git v1.7.0-rc0 - merge ), l' git -Coption n'était pas encore disponible (puisqu'elle a été introduite dans 44e1e4d67d (" git: exécutée dans un répertoire donné with -C option ", 2013-09-09, Git v1.8.5-rc0 - fusion répertoriée dans le lot # 5 )).
En conséquence, la fonction d'assistance a supprimé la nécessité de manuellement à cdchaque fois. Cependant, étant donné qu'il git -Cest disponible maintenant, nous pouvons simplement l'utiliser à la place et en ligne full_name().

VonC
la source
6
Wow, sympa! C'est beaucoup plus élégant, donc je vais le marquer comme accepté pour les futurs téléspectateurs.
Gavin Anderegg
1
Ne fonctionne pas pour moi: # git --version && git -C ~ / .m2 / checkout master git version 1.8.3.4 (Apple Git-47) Option inconnue: -C utilisation: git [--version] [--help ] [-c nom = valeur] [--exec-chemin [= <chemin>]] [--html-chemin] [--man-chemin] [--info-chemin] [-p | --paginate | --no-pager] [--no-replace-objects] [--bare] [--git-dir = <path>] [--work-tree = <path>] [--namespace = <name> ] <commande> [<args>]
Jan Galinski
7
@JanGalinski Mais j'ai mentionné "Démarrage de git 1.8.5". Donc git 1.8.3.x ne connaîtrait pas encore cette option.
VonC
2
Sur Ubuntu 12.04, j'ai dû installer une version git plus récente. Je l'ai fait comme ça: apt-get install software-properties-common python-software-propertiespuis ajoutez le git repo add-apt-repository ppa:git-core/ppa. La dernière étape consiste à mettre à jour git: apt-get update && apt-get upgrade.
ph3nx
54

Modifier :

Il y a soit un bug avec git pull, soit vous ne pouvez pas faire ce que vous essayez de faire avec cette commande. Vous pouvez cependant le faire avec l'extraction et la fusion:

cd /X
git --git-dir=/X/Y/.git fetch
git --git-dir=/X/Y/.git --work-tree=/X/Y merge origin/master

Réponse originale :

En supposant que vous exécutez bash ou similaire, vous pouvez le faire (cd /X/Y; git pull).

La page de manuel de git spécifie certaines variables (voir "Le référentiel git") qui semblent devoir aider, mais je ne peux pas les faire fonctionner correctement (avec mon référentiel dans / tmp / ggg2):

GIT_WORK_TREE=/tmp/ggg2 GIT_DIR=/tmp/ggg2/.git git pull
fatal: /usr/lib/git-core/git-pull cannot be used without a working tree.

L'exécution de la commande ci-dessous pendant que mon cwd est / tmp met à jour ce dépôt, mais le fichier mis à jour apparaît dans / tmp au lieu de l'arborescence de travail / tmp / ggg2:

GIT_DIR=/tmp/ggg2/.git git pull

Voir également cette réponse à une question similaire , qui illustre les indicateurs --git-diret --work-tree.

bstpierre
la source
Avez-vous essayé d'utiliser uniquement GIT_WORK_TREE?
Arrowmaster
@Arrowmaster: oui, si vous le faites, git ne peut pas trouver le .gitrépertoire.
bstpierre
Ah oui, la page de manuel indique que GIT_WORK_TREE n'est pas utilisé si GIT_DIR n'est pas défini. Il semble étrange que cela ne fonctionne pas lorsque les deux sont utilisés.
Arrowmaster
@Arrowmaster: Je dois me demander s'il y a un bug ici quelque part. Si je le fais git --git-dir=/tmp/ggg2/.git --work-tree=/tmp/ggg2 pull, j'obtiens un message d'erreur. Mais si je le fais git --git-dir=/tmp/ggg2/.git --work-tree=. pullpendant que je suis dans / tmp, il place les fichiers mis à jour dans / tmp comme il se doit.
bstpierre
@bstpierre: Je n'ai pas accès à un système avec git installé en ce moment, mais si je le faisais, j'essaierais d'autres alternatives en --work-treece moment --work-tree=/tmp/ggg2/et --work-tree=/tmp/ggg2/.comme cela pourrait être un problème avec la façon dont il analyse le chemin.
Arrowmaster
32

Vous pouvez l'encapsuler dans un script bash ou un alias git:

cd /X/Y && git pull && cd -
takhin
la source
1
Cela fait définitivement l'affaire, mais je me demande s'il existe un moyen d'utiliser la commande git sans changer de répertoire. Je commence à penser qu'il n'y en a pas.
Gavin Anderegg
1
et utilisez la pushd/popdpaire au lieu decd/cd-
axd
Ou vous pouvez utiliser un sous-shell pour éviter d'avoir à revenir en arrière:(cd xyz && git pull)
jarmod
30

Ce message est un peu ancien, donc il pourrait y avoir un bug et il a été corrigé, mais je viens de le faire:

git --work-tree=/X/Y --git-dir=/X/Y/.git pull origin branch

Et ça a marché. Cela m'a pris une minute pour comprendre qu'il voulait le fichier dot et le répertoire parent (dans une configuration standard, ils sont toujours parents / enfants mais pas dans TOUTES les configurations, ils doivent donc être spécifiés explicitement.

samtresler
la source
J'aime cette solution car elle fonctionne avec des répertoires comme \\ remotemachine \ C $ \ folder \ etc
twasbrillig
7

Comme certains de mes serveurs sont sur une ancienne version d'Ubuntu LTS, je ne peux pas facilement mettre à niveau git vers la dernière version (qui prend en charge l'option -C comme décrit dans certaines réponses).

Cette astuce fonctionne bien pour moi, surtout parce qu'elle n'a pas l'effet secondaire d'autres réponses qui vous laissent dans un répertoire différent de celui où vous avez commencé.

pushd /X/Y
git pull
popd

Ou, en le faisant en une ligne:

pushd /X/Y; git pull; popd

Linux et Windows ont tous deux des commandes pushd et popd.

IvanD
la source
5

En utilisant la combinaison pushd, git pullet popd, nous pouvons atteindre cette fonctionnalité:

pushd <path-to-git-repo> && git pull && popd

Par exemple:

pushd "E:\Fake Directory\gitrepo" && git pull && popd
Raman Sahasi
la source
Ceci est incroyable. Fonctionne parfaitement
Stretch0
4

Vous pouvez écrire un script comme celui-ci:

cd /X/Y
git pull

Vous pouvez le nommer quelque chose comme gitpull.
Si vous préférez qu'il fasse des répertoires arbitraires au lieu de /X/Y:

cd $1
git pull

Ensuite, vous pouvez l'appeler avec gitpull /X/Z
Lastly, vous pouvez essayer de trouver des référentiels. J'ai un ~/gitdossier qui contient des référentiels, et vous pouvez l'utiliser pour faire un pull sur chacun d'eux.

g=`find /X -name .git`
for repo in ${g[@]}
do
    cd ${repo}
    cd ..
    git pull
done
jonescb
la source
2
Si vous voulez le faire à partir de la ligne de commande, il suffit de faire dans un sous - shell: (cd /X/Y && git pull).
Cascabel
2

Pour quelqu'un comme moi qui tentait de le faire via une commande drush (Drupal shell) sur un serveur distant, vous ne pourrez pas utiliser la solution qui vous oblige à CD dans le répertoire de travail:

Au lieu de cela, vous devez utiliser la solution qui décompose le pull en fetch & merge:

drush @remote exec git --git-dir=/REPO/PATH --work-tree=/REPO/WORKDIR-PATH fetch origin
drush @remote exec git --git-dir=/REPO/PATH --work-tree=/REPO/WORKDIR-PATH merge origin/branch
dkinzer
la source
1

Cela peut être un problème similaire, mais vous pouvez également simplement enchaîner vos commandes. par exemple

Sur une seule ligne

cd ~/Sites/yourdir/web;git pull origin master

Ou via SSH.

ssh [email protected] -t "cd ~/Sites/thedir/web;git pull origin master"
John Ballinger
la source