git pull ขณะที่ไม่อยู่ในไดเรกทอรี git


308

สมมติว่าฉันมีไดเรกทอรี/X/Yซึ่งเป็นที่เก็บ git เป็นไปได้ไหมที่จะเรียกคำสั่งเช่นgit pullจากภายใน/Xแต่กำหนดเป้าหมาย/X/Yไดเรกทอรี?

แก้ไข:ฉันเดาว่าฉันสงสัยโดยเฉพาะ: เป็นไปได้ไหมที่จะใช้คำสั่ง git แต่ไม่ต้องเปลี่ยนไดเรกทอรี?

หมายเหตุ:ฉันยอมรับคำตอบของ VonCเนื่องจากมีความหรูหรามากกว่าตัวเลือกก่อนหน้า สำหรับคนทำงาน Git เก่ากว่า 1.8.5 โปรดดูคำตอบ bstpierre ด้านล่าง


2
ฉันต้องการเพิ่มเมื่อใช้ git-pull ภายใน hook จะไม่ทำงานจนกว่าคุณจะยกเลิกการตั้งค่า GIT_DIR ที่เกี่ยวข้อง
zpmorgan

การเริ่มต้น git 1.8.5 (Q4 2013) คุณจะสามารถ "ใช้คำสั่ง git แต่ไม่ต้องเปลี่ยนไดเรกทอรี" ดูคำตอบของฉันด้านล่าง
VonC

คำตอบ:


453

การเริ่มต้นgit 1.8.5 (Q4 2013)คุณจะสามารถ "ใช้คำสั่ง Git แต่ไม่ต้องเปลี่ยนไดเรกทอรี"

เช่นเดียวกับ " make -C <directory>" " git -C <directory> ..." บอก Git ไปที่นั่นก่อนที่จะทำอะไรอย่างอื่น

ดูการกระทำ 44e1e4โดยNazri Ramliy :

ใช้การกดคีย์เพิ่มเติมเพื่อเรียกใช้คำสั่ง Git ในไดเรกทอรีอื่นโดยไม่ต้องออกจากไดเรกทอรีปัจจุบัน:

  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

วิธีการที่แสดงด้านบนเป็นที่ยอมรับได้สำหรับการสร้างสคริปต์ แต่ยุ่งยากเกินไปสำหรับการเรียกใช้บรรทัดคำสั่งด่วน

ด้วยตัวเลือกใหม่นี้สามารถทำได้โดยการกดปุ่มน้อยลง:

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

ตั้งแต่ Git 2.3.4 (มีนาคม 2015) และกระทำ 6a536e2โดยคาร์ทิคยัก ( KarthikNayak) , gitจะปฏิบัติต่อ " git -C '<path>'" เป็นไม่มี-op เมื่อ<path>เป็นที่ว่างเปล่า

' git -C ""' ตายอย่างไม่ช่วยเหลือด้วยความผิดพลาด " Cannot change to ''" ในขณะที่เชลล์ปฏิบัติต่อ cd "" 'เป็นแบบไม่มี op
การใช้พฤติกรรมของเชลล์เป็นแบบอย่างให้สอนgitเพื่อรักษา -C "" 'เป็นตัวเลือกไม่เช่นกัน


4 ปีต่อมา Git 2.23 (Q3 2019) เอกสารที่ใช้git -C ""งานได้และไม่เปลี่ยนไดเรกทอรี

มันทำงานได้ตั้งแต่ 6a536e2 ( git: ถือว่า " git -C '<path>'" เป็นแบบไม่เปิดเมื่อ<path>ว่างเปล่า 2015-03-06, Git v2.3.4)

นั่นหมายถึงเอกสารตอนนี้ (ในที่สุด) รวมถึง:

หาก ' <path>' มีอยู่ แต่ว่างเปล่าเช่น-C ""ไดเรกทอรีการทำงานปัจจุบันจะไม่เปลี่ยนแปลง


คุณสามารถดูการgit -Cใช้กับ Git 2.26 (ไตรมาสที่ 1 ปี 2020) เป็นตัวอย่าง

ดูกระทำ b441717 , กระทำ 9291e63 , กระทำ 5236fce , กระทำ 10812c2 , กระทำ 62d58cd , กระทำ b87b02c , กระทำ 9b92070 , กระทำ 3595d10 , กระทำ f511bc0 , กระทำ f6041ab , กระทำ f46c243 , กระทำ 99c049b , กระทำ 3738439 , กระทำ 7717242 , กระทำ b8afb90 (20 ธันวาคม 2019) โดยDenton หลิว (Denton-L )
(รวมโดยJunio C Hamano - gitster-ในการกระทำ 381e8e9 , 5 กุมภาพันธ์ 2020)

t1507: อินไลน์ full_name()

ลงชื่อออกโดย: Denton Liu

test_must_fail full_nameก่อนที่เรากำลังวิ่ง อย่างไรก็ตามtest_must_failควรใช้กับคำสั่ง git เท่านั้น
แบบอินไลน์full_name()เพื่อให้เราสามารถใช้test_must_failกับgitคำสั่งโดยตรง

เมื่อfull_name()ถูกนำมาใช้ใน28fb84382b ("แนะนำ<branch>@{upstream}เครื่องหมาย", 2009-09-10, Git v1.7.0-rc0 - ผสาน ) git -Cตัวเลือกยังไม่พร้อมใช้งาน (ตั้งแต่เปิดตัวใน44e1e4d67d (" git: เรียกใช้ในไดเรกทอรีที่กำหนด ด้วยตัวเลือก -C ", 2013-09-09, Git v1.8.5-rc0 - ผสานอยู่ในรายการแบทช์ # 5 ))
เป็นผลให้ฟังก์ชั่นตัวช่วยลบความต้องการด้วยตนเองออกcdทุกครั้ง อย่างไรก็ตามเนื่องจากgit -Cมีให้บริการในตอนนี้เราสามารถใช้แทนและอินไลน์full_name()ได้


6
ว้าวดี! นี่เป็นวิธีที่ดูดีกว่าดังนั้นฉันจะทำเครื่องหมายว่าเป็นที่ยอมรับสำหรับผู้ชมในอนาคต
กาวิน Anderegg

1
ไม่ทำงานสำหรับฉัน: # git - รุ่น && git -C ~ / .m2 / เช็คเอาต์หลัก git รุ่น 1.8.3.4 (Apple Git-47) ตัวเลือกที่ไม่รู้จัก: การใช้งาน -C: git [--version] [- ช่วย ] [-c name = value] [--exec-path [= <path>]] [--html-path] [--man-path] [--info-path] [-p | --paginate | - ไม่มีเพจเจอร์] [- ไม่มี - แทนที่วัตถุ] [--bare] [--git-dir = <path>] [--work-tree = <path>] [--namespace = <name> ] <command> [<args>]
Jan Galinski

7
@JanGalinski แต่ฉันไม่ได้พูดถึง "เริ่มต้น git 1.8.5" ดังนั้น git 1.8.3.x ยังไม่รู้เกี่ยวกับตัวเลือกนั้น
VonC

2
บน Ubuntu 12.04 ฉันต้องติดตั้งเวอร์ชัน git ที่ใหม่กว่า ฉันไม่ได้เช่นนี้apt-get install software-properties-common python-software-propertiesแล้วเพิ่ม add-apt-repository ppa:git-core/pparepo ขั้นตอนสุดท้ายคือการคอมไพล์ apt-get update && apt-get upgradeUPDATE:
ph3nx


54

แก้ไข :

มีข้อบกพร่องด้วยgit pullหรือคุณไม่สามารถทำสิ่งที่คุณพยายามจะทำกับคำสั่งนั้น อย่างไรก็ตามคุณสามารถทำได้ด้วยการดึงข้อมูลและผสาน:

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

คำตอบเดิม :

(cd /X/Y; git pull)สมมติว่าคุณกำลังทำงานทุบตีหรือคล้ายกันที่คุณสามารถทำได้

หน้าคนคอมไพล์ระบุตัวแปรบาง (ดู "การคอมไพล์ Repository") ที่ดูเหมือนพวกเขาจะช่วย แต่ฉันไม่สามารถทำให้พวกเขาทำงานขวา (ที่มีพื้นที่เก็บข้อมูลของฉันใน / 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.

เรียกใช้คำสั่งด้านล่างในขณะที่ cwd ของฉันคือ / tmp อัพเดตที่ repo แต่ไฟล์ที่อัพเดทปรากฏใน / tmp แทนต้นไม้ทำงาน / tmp / ggg2:

GIT_DIR=/tmp/ggg2/.git git pull

ดูคำตอบนี้สำหรับคำถามที่คล้ายกันซึ่งแสดงให้เห็นถึง--git-dirและ--work-treeธง


คุณลองใช้เพียง GIT_WORK_TREE หรือไม่
Arrowmaster

@Arrowmaster: ใช่ถ้าคุณทำเช่นนั้นคอมไพล์ไม่พบ.gitไดเรกทอรี
bstpierre

อ่าหน้าคนบอกว่า GIT_WORK_TREE ไม่ได้ใช้หากไม่ได้ตั้ง GIT_DIR ดูเหมือนว่ามันจะไม่ทำงานเมื่อทั้งคู่ถูกใช้งาน
Arrowmaster

@ Arrowmaster: ฉันต้องสงสัยว่ามีข้อผิดพลาดที่นี่ที่ไหนสักแห่ง ถ้าฉันทำgit --git-dir=/tmp/ggg2/.git --work-tree=/tmp/ggg2 pullฉันได้รับข้อความแสดงข้อผิดพลาด แต่ถ้าฉันทำgit --git-dir=/tmp/ggg2/.git --work-tree=. pullในขณะที่ฉันอยู่ใน / tmp มันทำให้ไฟล์ที่อัปเดตเป็น / tmp เท่าที่ควร
bstpierre

@bstpierre: ฉันไม่สามารถเข้าถึงระบบที่ติดตั้ง git ได้ในตอนนี้ แต่ถ้าฉันทำฉันจะลองใช้ทางเลือกอื่น ๆ--work-treeในตอนนี้--work-tree=/tmp/ggg2/และ--work-tree=/tmp/ggg2/.เนื่องจากอาจเป็นปัญหาเกี่ยวกับวิธีการแยกวิเคราะห์เส้นทาง
Arrowmaster

32

คุณสามารถใส่มันในสคริปต์ทุบตีหรือนามแฝงคอมไพล์:

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

1
นี่เป็นกลอุบายอย่างแน่นอน แต่ฉันสงสัยว่ามีวิธีใช้คำสั่ง git โดยไม่ต้องเปลี่ยนไดเรกทอรีหรือไม่ ฉันเริ่มคิดว่าไม่มี
Gavin Anderegg

1
และใช้pushd/popdคู่แทนcd/cd-
axd

หรือคุณอาจจะใช้ subshell เพื่อป้องกันไม่ให้มีการกลับ cd:(cd xyz && git pull)
jarmod

30

โพสต์นี้ค่อนข้างเก่าดังนั้นอาจมีข้อผิดพลาดและแก้ไขแล้ว แต่ฉันเพิ่งทำสิ่งนี้:

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

และมันก็ใช้งานได้ ใช้เวลาสักครู่ในการคิดว่ามันต้องการ dotfile และไดเรกทอรีหลัก (ในการตั้งค่ามาตรฐานที่เป็นผู้ปกครอง / ลูกเสมอ แต่ไม่ใช่ในการตั้งค่าทั้งหมดดังนั้นพวกเขาจำเป็นต้องระบุอย่างชัดเจน


ฉันชอบโซลูชันนี้เพราะทำงานกับไดเรกทอรีเช่น \\ remotemachine \ C $ \ folder \ etc
twasbrillig

7

เนื่องจากเซิร์ฟเวอร์บางตัวของฉันใช้ Ubuntu LTS รุ่นเก่าฉันไม่สามารถอัพเกรด git เป็นเวอร์ชันล่าสุดได้อย่างง่ายดาย (ซึ่งรองรับตัวเลือก -C ตามที่อธิบายไว้ในคำตอบบางข้อ)

เคล็ดลับนี้ใช้งานได้ดีสำหรับฉันโดยเฉพาะอย่างยิ่งเนื่องจากไม่มีผลข้างเคียงของคำตอบอื่น ๆ ที่ทำให้คุณอยู่ในไดเรกทอรีที่แตกต่างจากที่คุณเริ่ม

pushd /X/Y
git pull
popd

หรือทำมันเป็นหนึ่งซับ:

pushd /X/Y; git pull; popd

ทั้ง Linux และ Windows มีคำสั่ง pushd และ popd


5

โดยใช้การรวมpushd, git pullและpopdเราสามารถบรรลุการทำงานนี้:

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

ตัวอย่างเช่น:

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

สิ่งนี้ช่างมหัศจรรย์. ทำงานได้อย่างสมบูรณ์แบบ
Stretch0

4

คุณสามารถเขียนสคริปต์เช่นนี้:

cd /X/Y
git pull

gitpullคุณสามารถตั้งชื่อสิ่งที่ต้องการ
หากคุณต้องการให้มันทำไดเรกทอรีโดยพลการแทน/X/Y:

cd $1
git pull

จากนั้นคุณสามารถโทรหาได้ด้วยgitpull /X/Z
สุดท้ายคุณสามารถลองค้นหาที่เก็บ ฉันมี~/gitโฟลเดอร์ที่มีที่เก็บและคุณสามารถใช้มันเพื่อดึงทั้งหมด

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

2
หากคุณต้องการที่จะทำจากบรรทัดคำสั่งเพียงแค่ทำมันใน subshell (cd /X/Y && git pull)นี้:
Cascabel

2

สำหรับทุกคนอย่างฉันที่พยายามทำสิ่งนี้ผ่านคำสั่ง drush (เชลล์ Drupal) บนเซิร์ฟเวอร์ระยะไกลคุณจะไม่สามารถใช้โซลูชันที่กำหนดให้คุณต้องใช้ซีดีในไดเรกทอรีการทำงาน:

แต่คุณต้องใช้โซลูชันที่ดึงการดึงและการรวม:

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

นี่อาจเป็นปัญหาที่คล้ายกัน แต่คุณสามารถเชื่อมโยงคำสั่งของคุณ เช่น

ในหนึ่งบรรทัด

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

หรือผ่าน SSH

ssh username@atyourserver.com -t "cd ~/Sites/thedir/web;git pull origin master"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.