Git Pull, während nicht in einem Git-Verzeichnis

308

Angenommen, ich habe ein Verzeichnis, /X/Ybei dem es sich um ein Git-Repository handelt. Ist es möglich, einen Befehl wie git pullvon innen aufzurufen /X, aber auf das /X/YVerzeichnis abzuzielen ?

EDIT: Ich glaube, ich habe mich speziell gefragt: Ist es möglich, dies mit dem Befehl a git zu tun, ohne die Verzeichnisse ändern zu müssen?

HINWEIS: Ich habe die Antwort von VonC akzeptiert , da sie viel eleganter ist als die vorherigen Optionen. Für Leute, die Git älter als 1.8.5 ausführen, lesen Sie bitte die Antwort von bstpierre unten .

Gavin Anderegg
quelle
2
Ich möchte hinzufügen, dass bei Verwendung von Git-Pull innerhalb eines Hooks nur funktioniert, wenn Sie GIT_DIR deaktivieren. Relevant.
zpmorgan
Ab Git 1.8.5 (Q4 2013) können Sie "einen Git-Befehl verwenden, ohne jedoch die Verzeichnisse wechseln zu müssen". Siehe meine Antwort unten
VonC

Antworten:

453

Ab Git 1.8.5 (Q4 2013) können Sie "einen Git-Befehl verwenden, ohne jedoch die Verzeichnisse wechseln zu müssen".

Genau wie „ make -C <directory>“, git -C <directory> ...“ sagt Git , dorthin zu gehen , bevor irgendetwas anderes zu tun .

Siehe Commit 44e1e4 von Nazri Ramliy :

Es sind mehr Tastendrücke erforderlich, um den Git-Befehl in einem anderen Verzeichnis aufzurufen, ohne das aktuelle Verzeichnis zu verlassen:

  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

Die oben gezeigten Methoden sind für die Skripterstellung akzeptabel, für schnelle Befehlszeilenaufrufe jedoch zu umständlich.

Mit dieser neuen Option können die oben genannten Schritte mit weniger Tastenanschlägen ausgeführt werden:

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

Seit Git 2.3.4 (März 2015), und verpflichten 6a536e2 von Karthik Nayak ( KarthikNayak) , gitbehandeln wird " git -C '<path>'" als no-op , wenn <path>leer.

' git -C ""' stirbt unbeholfen mit dem Fehler " Cannot change to ''", während die Shell cd "" als No-Op behandelt.
Nehmen Sie das Verhalten der Shell als Präzedenzfall und lehren Sie git, -C "" 'auch als No-Op zu behandeln.


4 Jahre später dokumentiert Git 2.23 (Q3 2019), dass ' git -C ""' funktioniert und das Verzeichnis nicht wechselt

Es verhält sich seit 6a536e2 so ( git: " git -C '<path>'" als No-Op behandeln, wenn <path>es leer ist, 2015-03-06, Git v2.3.4).

Das heißt, die Dokumentation enthält jetzt (endlich):

Wenn ' <path>' vorhanden, aber leer ist, z. B. -C "", bleibt das aktuelle Arbeitsverzeichnis unverändert.


Sie können git -Cals Beispiel die Verwendung mit Git 2.26 (Q1 2020) sehen.

Sehen Sie verpflichten b441717 , begehen 9291e63 , begehen 5236fce , begehen 10812c2 , begehen 62d58cd , begehen b87b02c , begehen 9b92070 , begehen 3595d10 , begehen f511bc0 , begehen f6041ab , begehen f46c243 , begehen 99c049b , begehen 3.738.439 , begehen 7.717.242 , begehen b8afb90 (20. Dezember 2019) von Denton Liu ( Denton-L) .
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit 381e8e9 , 05. Februar 2020)

t1507: in der Reihe full_name()

Unterzeichnet von: Denton Liu

Vorher rannten wir test_must_fail full_name. Sollte test_must_failjedoch nur für Git-Befehle verwendet werden.
Inline, full_name()damit wir test_must_failden gitBefehl direkt verwenden können.

Bei full_name()der Einführung in 28fb84382b ("Introduce <branch>@{upstream}notation", 10.09.2009, Git v1.7.0-rc0 - merge ) war die git -COption noch nicht verfügbar (da sie in 44e1e4d67d eingeführt wurde (" git: in einem angegebenen Verzeichnis ausführen) mit der Option -C ", 09.09.2013, Git v1.8.5-rc0 - Zusammenführung in Stapel 5 aufgeführt )).
Infolgedessen wurde durch die Hilfsfunktion die Notwendigkeit beseitigt, cdjedes Mal manuell zu arbeiten. Da git -Ces jetzt verfügbar ist, können wir es stattdessen einfach und inline verwenden full_name().

VonC
quelle
6
Wow nett! Dies ist viel eleganter, daher werde ich es für zukünftige Zuschauer als akzeptiert markieren.
Gavin Anderegg
1
Funktioniert bei mir nicht: # git --version && git -C ~ / .m2 / checkout master git Version 1.8.3.4 (Apple Git-47) Unbekannte Option: -C Verwendung: git [--version] [--help ] [-c name = value] [--exec-path [= <path>]] [--html-path] [--man-path] [--info-path] [-p | --paginate | --no-pager] [--no-replace-Objekte] [--bare] [--git-dir = <Pfad>] [--work-tree = <Pfad>] [--namespace = <Name> ] <Befehl> [<Args>]
Jan Galinski
7
@ JanGalinski Aber ich habe "Starting git 1.8.5" erwähnt. Git 1.8.3.x würde also noch nichts über diese Option wissen.
VonC
2
Unter Ubuntu 12.04 musste ich eine neuere Git-Version installieren. Ich habe es so gemacht: apt-get install software-properties-common python-software-propertiesdann füge das Git Repo hinzu add-apt-repository ppa:git-core/ppa. Der letzte Schritt ist das Aktualisieren von git : apt-get update && apt-get upgrade.
Ph3nx
54

Bearbeiten :

Es gibt entweder einen Fehler mit git pulloder Sie können nicht das tun, was Sie mit diesem Befehl versuchen. Sie können dies jedoch mit Abrufen und Zusammenführen tun:

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

Ursprüngliche Antwort :

Angenommen, Sie führen Bash oder ähnliches aus, können Sie dies tun (cd /X/Y; git pull).

Die Git-Manpage gibt einige Variablen an (siehe "Das Git-Repository"), die helfen sollen, aber ich kann sie nicht richtig funktionieren lassen (mit meinem 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.

Wenn Sie den folgenden Befehl ausführen, während mein cwd / tmp ist, wird das Repo aktualisiert, aber die aktualisierte Datei wird in / tmp anstelle des Arbeitsbaums / tmp / ggg2 angezeigt:

GIT_DIR=/tmp/ggg2/.git git pull

Siehe auch diese Antwort auf eine ähnliche Frage , die die --git-dirund --work-tree-Flaggen demonstriert .

bstpierre
quelle
Haben Sie versucht, nur GIT_WORK_TREE zu verwenden?
Arrowmaster
@Arrowmaster: Ja, wenn du das tust, kann Git das .gitVerzeichnis nicht finden .
Bstpierre
Ah richtig, die Manpage sagt, dass GIT_WORK_TREE nicht verwendet wird, wenn GIT_DIR nicht gesetzt ist. Es scheint seltsam, dass es dann nicht funktioniert, wenn beide verwendet werden.
Arrowmaster
@Arrowmaster: Ich muss mich fragen, ob es hier irgendwo einen Fehler gibt. In diesem git --git-dir=/tmp/ggg2/.git --work-tree=/tmp/ggg2 pullFall wird eine Fehlermeldung angezeigt. Wenn ich dies jedoch tue, git --git-dir=/tmp/ggg2/.git --work-tree=. pullwährend ich in / tmp bin, werden die aktualisierten Dateien wie gewünscht in / tmp abgelegt.
Bstpierre
@bstpierre: Ich habe keinen Zugriff auf ein System mit git jetzt installiert , aber wenn ich es täte würde ich mit anderen Alternativen versuchen --work-treejetzt , wie --work-tree=/tmp/ggg2/und --work-tree=/tmp/ggg2/.da könnte es ein Problem mit , wie es der Pfad Parsen.
Arrowmaster
32

Sie können es in ein Bash-Skript oder einen Git-Alias ​​einbinden:

cd /X/Y && git pull && cd -
Takeshin
quelle
1
Dies ist definitiv der Trick, aber ich frage mich, ob es eine Möglichkeit gibt, den Befehl git zu verwenden, ohne die Verzeichnisse zu ändern. Ich fange an zu denken, dass es keine gibt.
Gavin Anderegg
1
und benutze das pushd/popdPaar anstelle voncd/cd-
axd
Oder Sie könnten eine Unterschale verwenden, um zu verhindern, dass Sie zurück cd müssen:(cd xyz && git pull)
jarmod
30

Dieser Beitrag ist ein bisschen alt, also könnte es einen Fehler geben und er wurde behoben, aber ich habe dies einfach getan:

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

Und es hat funktioniert. Ich habe eine Minute gebraucht, um herauszufinden, dass die Punktdatei und das übergeordnete Verzeichnis benötigt werden (in einem Standard-Setup sind dies immer Eltern / Kind, aber nicht in ALLEN Setups, daher müssen sie explizit angegeben werden.

Samtresler
quelle
Ich mag diese Lösung, weil sie mit Verzeichnissen wie \\ remotemachine \ C $ \
folder
7

Da sich einige meiner Server auf einer alten Ubuntu LTS-Version befinden, kann ich git nicht einfach auf die neueste Version aktualisieren (die die Option -C unterstützt, wie in einigen Antworten beschrieben).

Dieser Trick funktioniert gut für mich, insbesondere weil er nicht die Nebenwirkung einiger anderer Antworten hat, die Sie in einem anderen Verzeichnis belassen, als Sie begonnen haben.

pushd /X/Y
git pull
popd

Oder als Einzeiler:

pushd /X/Y; git pull; popd

Sowohl Linux als auch Windows verfügen über Pushd- und Popd-Befehle.

IvanD
quelle
5

Mit Kombination pushd, git pullund popdwir diese Funktionalität erreichen können:

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

Zum Beispiel:

pushd "E:\Fake Directory\gitrepo" && git pull && popd
Raman Sahasi
quelle
das ist großartig. Funktioniert perfekt
Stretch0
4

Sie können ein Skript wie folgt schreiben:

cd /X/Y
git pull

Sie können es so etwas wie nennen gitpull.
Wenn Sie es lieber haben möchten, machen Sie beliebige Verzeichnisse anstelle von /X/Y:

cd $1
git pull

Dann können Sie es mit gitpull /X/Z
Zuletzt können Sie versuchen, Repositorys zu finden. Ich habe einen ~/gitOrdner, der Repositorys enthält, und Sie können diesen verwenden, um alle abzurufen.

g=`find /X -name .git`
for repo in ${g[@]}
do
    cd ${repo}
    cd ..
    git pull
done
jonescb
quelle
2
Wenn Sie dies über die Befehlszeile tun möchten, tun Sie es einfach in einer Subshell : (cd /X/Y && git pull).
Cascabel
2

Für jemanden wie mich, der dies über einen Drush-Befehl (Drupal-Shell) auf einem Remote-Server versucht hat, können Sie die Lösung nicht verwenden, für die Sie eine CD in das Arbeitsverzeichnis benötigen:

Stattdessen müssen Sie die Lösung verwenden, die den Pull in ein Fetch & Merge aufteilt:

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
quelle
1

Dies mag ein ähnliches Problem sein, aber Sie können Ihre Befehle auch einfach verketten. z.B

In einer Zeile

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

Oder über SSH.

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