git pull mentre non si trova in una directory git


308

Diciamo che ho una directory /X/Y, che è un repository git. È possibile in qualche modo chiamare un comando come git pulldall'interno /X, ma indirizzare la /X/Ydirectory?

EDIT: Immagino che mi stavo chiedendo specificamente: è possibile farlo usando il comando a git, ma senza cambiare directory?

NOTA: ho accettato la risposta di VonC in quanto è molto più elegante delle opzioni precedenti. Per le persone che eseguono Git di età superiore a 1.8.5, vedere la risposta di bstpierre di seguito .


2
Vorrei aggiungere che quando si utilizza git-pull in un hook non funzionerà a meno che non si disattivi GIT_DIR. Pertinente.
zpmorgan,

A partire da git 1.8.5 (Q4 2013), sarai in grado di "usare un comando git, ma senza cambiare directory". Vedi la mia risposta qui sotto
VonC

Risposte:


453

A partire da git 1.8.5 (Q4 2013) , sarai in grado di "usare un comando Git, ma senza cambiare directory".

Proprio come " make -C <directory>", " git -C <directory> ..." dice a Git di andarci prima di fare qualsiasi altra cosa .

Vedi commit 44e1e4 di Nazri Ramliy :

Sono necessari più tasti per richiamare il comando Git in una directory diversa senza uscire dalla directory corrente:

  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

I metodi sopra indicati sono accettabili per gli script ma sono troppo ingombranti per invocazioni rapide da riga di comando.

Con questa nuova opzione, quanto sopra può essere fatto con un minor numero di tasti:

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

Da Git 2.3.4 (marzo 2015), e commettere 6a536e2 da Karthik Nayak ( KarthikNayak) , gittratteranno " git -C '<path>'" come no-op quando <path>è vuoto.

' git -C ""' muore inutilmente con errore " Cannot change to ''", mentre la shell tratta cd "" 'come no-op.
Prendendo il comportamento della shell come un precedente, insegna anche gita trattare -C "" 'come no-op.


4 anni dopo, Git 2.23 (Q3 2019) documenta che ' git -C ""' funziona e non cambia directory

Si sta comportando così da 6a536e2 ( git: tratta " git -C '<path>'" come no-op quando <path>è vuoto, 2015-03-06, Git v2.3.4).

Ciò significa che la documentazione ora (finalmente) include:

Se ' <path>' è presente ma vuoto, ad es. -C "", L'attuale directory di lavoro rimane invariata.


Puoi vedere git -Cusato con Git 2.26 (Q1 2020), come esempio.

Vedi 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 7717242 , 208 2019 di Denton Liu ( Denton-L) .
(Unita da Junio ​​C Hamano - gitster- in commit 381e8e9 , 05 feb 2020)

t1507: in linea full_name()

Firmato-fuori-da: Denton Liu

Prima stavamo correndo test_must_fail full_name. Tuttavia, test_must_faildovrebbe essere usato solo sui comandi git.
In linea in full_name()modo che possiamo utilizzare direttamente test_must_failil gitcomando.

Quando è full_name()stato introdotto in 28fb84382b ("Introduce <branch>@{upstream}notation", 10/09/2009, Git v1.7.0-rc0 - merge ), l' git -Copzione non era ancora disponibile (poiché è stata introdotta in 44e1e4d67d (" git: esegui in una directory indicata con l'opzione -C ", 2013-09-09, Git v1.8.5-rc0 - unione elencata nel lotto n. 5 )).
Di conseguenza, la funzione di supporto ha rimosso la necessità di eseguire manualmente cdogni volta. Tuttavia, poiché git -Cè disponibile ora, possiamo semplicemente usarlo invece e in linea full_name().


6
Wow carino! È molto più elegante, quindi lo segnerò come accettato per i futuri spettatori.
Gavin Anderegg,

1
Per me non funziona: # git --version && git -C ~ / .m2 / checkout master git versione 1.8.3.4 (Apple Git-47) Opzione sconosciuta: -C utilizzo: git [--version] [--help ] [-c name = value] [--exec-path [= <path>]] [--html-path] [--man-path] [--info-path] [-p | --paginate | --no-pager] [--no-replace-objects] [--bare] [--git-dir = <percorso>] [--work-tree = <percorso>] [--namespace = <nome> ] <comando> [<args>]
Jan Galinski il

7
@JanGalinski Ma ho menzionato "Starting git 1.8.5". Quindi git 1.8.3.x non saprebbe ancora di quell'opzione.
VonC,

2
Su Ubuntu 12.04 ho dovuto installare una versione git più recente. L'ho fatto in questo modo: apt-get install software-properties-common python-software-propertiesquindi aggiungere il repository git add-apt-repository ppa:git-core/ppa. L'ultimo passo è quello di aggiornamento git: apt-get update && apt-get upgrade.
ph3nx,


54

Modifica :

C'è un bug con git pullo non puoi fare quello che stai cercando di fare con quel comando. È possibile però farlo con prendere e si fondono:

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

Risposta originale :

Supponendo che tu stia eseguendo bash o simili, puoi farlo (cd /X/Y; git pull).

La pagina man di git specifica alcune variabili (vedi "Il repository git") che sembrano aiutare, ma non riesco a farle funzionare bene (con il mio repository in / 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.

Eseguendo il comando di seguito mentre my cwd è / tmp aggiorna quel repository, ma il file aggiornato appare in / tmp invece che nell'albero di lavoro / tmp / ggg2:

GIT_DIR=/tmp/ggg2/.git git pull

Vedi anche questa risposta a una domanda simile , che dimostra i flag --git-dire --work-tree.


Hai provato a usare solo GIT_WORK_TREE?
Arrowmaster,

@Arrowmaster: sì, se lo fai, git non riesce a trovare la .gitdirectory.
bstpierre,

Ah giusto, la pagina man dice che GIT_WORK_TREE non viene usato se GIT_DIR non è impostato. Sembra strano che non funzioni quando vengono utilizzati entrambi.
Arrowmaster,

@Arrowmaster: devo chiedermi se c'è un bug qui da qualche parte. In tal caso git --git-dir=/tmp/ggg2/.git --work-tree=/tmp/ggg2 pull, viene visualizzato un messaggio di errore. Ma se lo faccio git --git-dir=/tmp/ggg2/.git --work-tree=. pullmentre sono in / tmp, inserisce i file aggiornati in / tmp come dovrebbe.
bstpierre,

@bstpierre: Non ho accesso a un sistema con git installato in questo momento ma se lo facessi proverei altre alternative con --work-treequesto tipo come --work-tree=/tmp/ggg2/e --work-tree=/tmp/ggg2/.poiché potrebbe essere un problema con il modo in cui analizza il percorso.
Arrowmaster,

32

Puoi avvolgerlo in uno script bash o git alias:

cd /X/Y && git pull && cd -

1
Questo sicuramente fa il trucco, ma mi chiedo se c'è un modo per usare il comando git senza cambiare directory. Sto iniziando a pensare che non ci sia.
Gavin Anderegg,

1
e usa la pushd/popdcoppia invece dicd/cd-
axd

Oppure potresti usare una subshell per evitare di dover (cd xyz && git pull)
ricodificare

30

Questo post è un po 'vecchio, quindi potrebbe esserci stato un bug ed è stato corretto, ma ho appena fatto questo:

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

E ha funzionato. Mi ci è voluto un minuto per capire che voleva il dotfile e la directory padre (in una configurazione standard quelli sono sempre padre / figlio ma non in TUTTE le configurazioni, quindi devono essere specificati in modo esplicito.


Mi piace questa soluzione perché funziona con directory come \\ remotemachine \ C $ \ folder \ etc
twasbrillig

7

Dato che alcuni dei miei server sono su una vecchia versione di Ubuntu LTS, non posso facilmente aggiornare git all'ultima versione (che supporta l'opzione -C come descritto in alcune risposte).

Questo trucco funziona bene per me, soprattutto perché non ha l'effetto collaterale di alcune altre risposte che ti lasciano in una directory diversa da dove hai iniziato.

pushd /X/Y
git pull
popd

Oppure, facendo come una linea:

pushd /X/Y; git pull; popd

Sia Linux che Windows hanno comandi pushd e popd.


5

Utilizzando combinazione pushd, git pulle popd, siamo in grado di ottenere questa funzionalità:

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

Per esempio:

pushd "E:\Fake Directory\gitrepo" && git pull && popd

è fantastico Funziona perfettamente
Stretch0

4

Puoi scrivere una sceneggiatura come questa:

cd /X/Y
git pull

Puoi nominarlo in qualche modo gitpull.
Se preferisci farlo, fai delle directory arbitrarie invece di /X/Y:

cd $1
git pull

Quindi puoi chiamarlo con gitpull /X/Z
Infine, puoi provare a trovare i repository. Ho una ~/gitcartella che contiene repository, e puoi usarlo per fare un pull su tutti.

g=`find /X -name .git`
for repo in ${g[@]}
do
    cd ${repo}
    cd ..
    git pull
done

2
Se si vuole farlo da riga di comando, basta farlo in una subshell: (cd /X/Y && git pull).
Cascabel,

2

Per chiunque come me che cercasse di farlo tramite un comando drush (shell Drupal) su un server remoto, non sarai in grado di usare la soluzione che richiede di CD nella directory di lavoro:

Invece devi usare la soluzione che spezza il pull in un 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

1

Questo potrebbe essere un problema simile, ma puoi anche semplicemente incatenare i tuoi comandi. per esempio

Su una riga

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

O tramite SSH.

ssh username@atyourserver.com -t "cd ~/Sites/thedir/web;git pull origin master"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.