git pull sementara tidak di direktori git

308

Katakanlah saya memiliki direktori /X/Y,, yang merupakan repositori git. Apakah mungkin memanggil perintah seperti git pulldari dalam/X , tetapi menargetkan /X/Ydirektori?

EDIT: Saya kira saya bertanya-tanya secara spesifik: apakah mungkin untuk melakukan ini menggunakan perintah a git, tetapi tanpa harus mengubah direktori?

CATATAN: Saya telah menerima jawaban VonC karena jauh lebih elegan daripada opsi sebelumnya. Untuk orang yang menggunakan Git lebih dari 1.8.5, silakan lihat jawaban bstpierre di bawah ini .

Gavin Anderegg
sumber
2
Saya ingin menambahkan bahwa ketika menggunakan git-pull dalam sebuah hook tidak akan berfungsi kecuali jika Anda membatalkan GIT_DIR. Relevan.
zpmorgan
Mulai git 1.8.5 (Q4 2013), Anda akan dapat "menggunakan perintah git, tetapi tanpa harus mengubah direktori". Lihat jawaban saya di bawah ini
VonC

Jawaban:

453

Mulai git 1.8.5 (Q4 2013) , Anda akan dapat "menggunakan perintah Git, tetapi tanpa harus mengubah direktori".

Sama seperti " make -C <directory>", " git -C <directory> ..." memberitahu Git untuk pergi ke sana sebelum melakukan hal lain .

Lihat commit 44e1e4 oleh Nazri Ramliy :

Dibutuhkan lebih banyak penekanan tombol untuk menjalankan perintah Git di direktori yang berbeda tanpa meninggalkan direktori saat ini:

  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

Metode yang ditunjukkan di atas dapat diterima untuk skrip tetapi terlalu rumit untuk pemanggilan baris perintah cepat.

Dengan opsi baru ini, hal di atas dapat dilakukan dengan sedikit penekanan tombol:

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

Sejak Git 2.3.4 (Maret 2015), dan melakukan 6a536e2 oleh Karthik Nayak ( KarthikNayak) , gitakan memperlakukan " git -C '<path>'" sebagai larangan ketika <path>kosong.

' git -C ""' tidak membantu mati dengan kesalahan " Cannot change to ''", sedangkan shell memperlakukan cd "" 'sebagai larangan.
Mengambil perilaku shell sebagai preseden, ajarkan gituntuk memperlakukan -C "" sebagai no-op, juga.


4 tahun kemudian, Git 2.23 (Q3 2019) mendokumentasikan bahwa ' git -C ""' berfungsi dan tidak mengubah direktori

Sudah bersikap sejak 6a536e2 ( git: perlakukan " git -C '<path>'" sebagai <path>larangan saat kosong, 2015-03-06, Git v2.3.4).

Itu berarti dokumentasi sekarang (akhirnya) meliputi:

Jika ' <path>' ada tetapi kosong, misalnya -C "", maka direktori kerja saat ini dibiarkan tidak berubah.


Anda dapat melihat git -Cdigunakan dengan Git 2.26 (Q1 2020), sebagai contoh.

Lihat komit b441717 , komit 9291e63 , komit 5236fce , komit 10812c2 , komit 62d58cd , komit b87b02c , komit 9b92070 , komit 3595d10 , komit f511bc0 , komit f6041ab , komit f46c243 , komit 99c049b , komit 3.738.439 , komit 7.717.242 , komit b8afb90 (20 Desember 2019) oleh Denton Liu ( Denton-L) .
(Digabung oleh Junio ​​C Hamano - gitster- dalam komit 381e8e9 , 05 Feb 2020)

t1507: Di barisan full_name()

Ditandatangani oleh: Denton Liu

Sebelumnya, kami berlari test_must_fail full_name. Namun, test_must_failseharusnya hanya digunakan pada perintah git.
Sebaris full_name()agar kita bisa menggunakan test_must_failpadagit perintah secara langsung.

Ketika full_name()diperkenalkan di 28fb84382b ("Introduce <branch>@{upstream}notation", 2009-09-10, Git v1.7.0-rc0 - merge ), git -Copsi belum tersedia (karena diperkenalkan di 44e1e4d67d (" git: jalankan di direktori yang diberikan dengan opsi -C ", 2013-09-09, Git v1.8.5-rc0 - gabung tercantum dalam batch # 5 )).
Akibatnya, fungsi helper menghilangkan kebutuhan secara manual cdsetiap kali. Namun, karena git -Csudah tersedia sekarang, kita bisa menggunakannya saja dan sebaris full_name().

VONC
sumber
6
Wow bagus! Ini jauh lebih elegan, jadi saya akan menandainya diterima untuk pemirsa di masa depan.
Gavin Anderegg
1
Tidak bekerja untuk saya: # git --version && git -C ~ / .m2 / checkout master git versi 1.8.3.4 (Apple Git-47) Opsi tidak dikenal: -C penggunaan: git [--version] [--help ] [-c name = value] [--exec-path [= <path>]] [--html-path] [--man-path] [--info-path] [-p | --paginate | --no-pager] [--no-ganti-objek] [--bare] [--git-dir = <path>] [--work-tree = <path>] [--namespace = <name> ] <command> [<args>]
Jan Galinski
7
@ JanGalinski Tapi saya memang menyebutkan "Starting git 1.8.5". Jadi git 1.8.3.x belum tahu tentang opsi itu.
VonC
2
Di Ubuntu 12.04 saya harus menginstal versi git yang lebih baru. Saya melakukannya seperti ini: apt-get install software-properties-common python-software-propertieslalu tambahkan repo git add-apt-repository ppa:git-core/ppa. Langkah terakhir adalah untuk memperbarui git: apt-get update && apt-get upgrade.
ph3nx
54

Edit :

Ada bug dengan git pull, atau Anda tidak dapat melakukan apa yang Anda coba lakukan dengan perintah itu. Namun Anda dapat melakukannya dengan mengambil dan menggabungkan:

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

Jawaban asli :

Dengan asumsi Anda menjalankan bash atau serupa, Anda bisa melakukannya (cd /X/Y; git pull).

Halaman git man menetapkan beberapa variabel (lihat "Gudang git") yang sepertinya membantu, tetapi saya tidak bisa membuatnya berfungsi dengan benar (dengan repositori saya di / 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.

Menjalankan perintah di bawah ini sementara cwd saya adalah / tmp memperbarui repo itu, tetapi file yang diperbarui muncul di / tmp alih-alih pohon kerja / tmp / ggg2:

GIT_DIR=/tmp/ggg2/.git git pull

Lihat juga jawaban ini untuk pertanyaan serupa , yang menunjukkan --git-dirdan --work-treebendera.

bstpierre
sumber
Apakah Anda mencoba menggunakan GIT_WORK_TREE?
Arrowmaster
@Arrowmaster: ya, jika Anda melakukannya, git tidak dapat menemukan .gitdirektori.
bstpierre
Ah benar, halaman manual mengatakan bahwa GIT_WORK_TREE tidak digunakan jika GIT_DIR tidak disetel. Tampaknya aneh bahwa itu tidak berfungsi saat keduanya digunakan.
Arrowmaster
@Arrowmaster: Saya harus bertanya-tanya apakah ada bug di suatu tempat. Jika saya melakukannya git --git-dir=/tmp/ggg2/.git --work-tree=/tmp/ggg2 pull, saya mendapatkan pesan kesalahan. Tetapi jika saya lakukan git --git-dir=/tmp/ggg2/.git --work-tree=. pullsaat saya di / tmp, itu menempatkan file yang diperbarui di / tmp sebagaimana mestinya.
bstpierre
@ bstpierre: Saya tidak memiliki akses ke sistem dengan git yang terinstal sekarang, tetapi jika saya melakukannya saya akan mencoba alternatif lain dengan --work-treesekarang seperti --work-tree=/tmp/ggg2/dan --work-tree=/tmp/ggg2/.karena itu bisa menjadi masalah dengan bagaimana cara mengurai path.
Arrowmaster
32

Anda dapat membungkusnya dalam skrip bash atau alias git:

cd /X/Y && git pull && cd -
takeshin
sumber
1
Ini memang berhasil, tetapi saya bertanya-tanya apakah ada cara untuk menggunakan perintah git tanpa mengubah direktori. Saya mulai berpikir bahwa tidak ada.
Gavin Anderegg
1
dan gunakan pushd/popdpasangan sebagai ganticd/cd-
axd
Atau Anda dapat menggunakan subkulit untuk mencegah keharusan melakukan cd kembali:(cd xyz && git pull)
jarmod
30

Posting ini agak lama sehingga bisa jadi ada bug dan diperbaiki, tapi saya baru saja melakukan ini:

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

Dan itu berhasil. Butuh beberapa saat untuk mencari tahu bahwa ia menginginkan direktori dotfile dan orang tua (dalam pengaturan standar yang selalu orangtua / anak tetapi tidak di SEMUA pengaturan, sehingga mereka perlu ditentukan secara eksplisit.

samtresler
sumber
Saya suka solusi ini karena ini bekerja dengan direktori seperti \\ remotemachine \ C $ \ folder \ etc
twasbrillig
7

Karena beberapa server saya menggunakan versi Ubuntu LTS lama, saya tidak dapat dengan mudah meningkatkan git ke versi terbaru (yang mendukung opsi -C seperti dijelaskan dalam beberapa jawaban).

Trik ini berfungsi baik untuk saya, terutama karena itu tidak memiliki efek samping dari beberapa jawaban lain yang membuat Anda berada di direktori yang berbeda dari tempat Anda memulai.

pushd /X/Y
git pull
popd

Atau, melakukannya sebagai one-liner:

pushd /X/Y; git pull; popd

Baik Linux dan Windows memiliki perintah pushd dan popd.

IvanD
sumber
5

Menggunakan kombinasi pushd, git pulldan popd, kami dapat mencapai fungsi ini:

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

Sebagai contoh:

pushd "E:\Fake Directory\gitrepo" && git pull && popd
Raman Sahasi
sumber
ini luar biasa. Berfungsi sempurna
Stretch0
4

Anda dapat menulis skrip seperti ini:

cd /X/Y
git pull

Anda dapat memberi nama sesuatu seperti itu gitpull.
Jika Anda lebih suka melakukannya lakukan direktori arbitrer daripada /X/Y:

cd $1
git pull

Kemudian Anda dapat menyebutnya dengan gitpull /X/Z
Terakhir, Anda dapat mencoba menemukan repositori. Saya memiliki ~/gitfolder yang berisi repositori, dan Anda dapat menggunakan ini untuk melakukan semuanya.

g=`find /X -name .git`
for repo in ${g[@]}
do
    cd ${repo}
    cd ..
    git pull
done
jonescb
sumber
2
Jika Anda ingin melakukannya dari baris perintah, lakukan saja di subkulit: (cd /X/Y && git pull).
Cascabel
2

Untuk orang seperti saya yang mencoba melakukan ini melalui perintah drush (Drupal shell) pada server jarak jauh, Anda tidak akan dapat menggunakan solusi yang mengharuskan Anda untuk CD ke direktori kerja:

Alih-alih, Anda perlu menggunakan solusi yang memecah tarikan menjadi mengambil & menggabungkan:

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

Ini mungkin masalah yang serupa, tetapi Anda juga dapat dengan mudah mengirim perintah. misalnya

Pada satu baris

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

Atau melalui SSH.

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