GIT: ชำระเงินไปยังโฟลเดอร์เฉพาะ


128

ฉันต้องการใช้สิ่งที่คล้ายกับ:

git checkout -- <path>/<file>

แต่ฉันต้องการเช็คเอาต์ไฟล์ไปยังโฟลเดอร์บางโฟลเดอร์ที่ฉันเลือกแทนที่จะเขียนทับใน<path>/<file>เครื่อง

ความคิดใด ๆ ?


คำตอบ:


57

ตามDo a "git export" (เช่น "svn export")?

คุณสามารถใช้git checkout-indexสำหรับที่นี้เป็นคำสั่งในระดับต่ำถ้าคุณต้องการที่จะส่งออกทุกอย่างคุณสามารถใช้-a,

git checkout-index -a -f --prefix=/destination/path/

หากต้องการอ้างถึงหน้าคน:

"/" สุดท้าย [บนคำนำหน้า] มีความสำคัญ ชื่อที่ส่งออกเป็นเพียงคำนำหน้าด้วยสตริงที่ระบุ

หากคุณต้องการส่งออกไดเร็กทอรีบางรายการมีเทคนิคบางอย่างที่เกี่ยวข้อง คำสั่งใช้เฉพาะไฟล์ไม่ใช่ไดเร็กทอรี หากต้องการนำไปใช้กับไดเร็กทอรีให้ใช้คำสั่ง 'find' และไพพ์เอาต์พุตไปยังคอมไพล์

find dirname -print0 | git checkout-index --prefix=/path-to/dest/ -f -z --stdin

นอกจากนี้จากหน้าคน:

สัญชาตญาณไม่ใช่เป้าหมายที่นี่ การทำซ้ำคือ


น่าเศร้าที่สิ่งนี้ใช้ไม่ได้จากที่เก็บ git เปล่าแม้จะมี --prefix set :-( (ทดสอบด้วย git 1.9.1)
apeiros

1
หากคุณต้องการตรวจสอบสาขา / คอมมิตของที่เก็บ git เปล่าให้ใช้GIT_WORK_TREE=../path/to/place git checkout
allicoder

4
git worktree(ดูด้านล่าง) imho เป็นคำตอบที่ยอมรับได้ในวันนี้และอาจเพิ่มที่นี่
geek-merlin

213

อีกวิธีหนึ่งที่สะอาดกว่าเล็กน้อยเพียงระบุแผนผังงานอื่น

ในการชำระเงินทุกอย่างตั้งแต่ HEAD ของคุณ (ไม่ใช่ดัชนี) ไปยังไดเร็กทอรีเอาต์เฉพาะ:

git --work-tree=/path/to/outputdir checkout HEAD -- .

ในการเช็คเอาต์ไดเร็กทอรีย่อยหรือไฟล์จาก HEAD ของคุณไปยังไดเร็กทอรีเฉพาะ:

git --work-tree=/path/to/outputdir checkout HEAD -- subdirname

4
หมายเหตุเล็กน้อย - คุณไม่จำเป็นต้องมีพา ธ สัมบูรณ์เนื่องจากการขยายตัวทิลเดอของเชลล์จะไม่เกิดขึ้นกล่าวคือ--work-tree=/home/thomasg/okcopyแทนที่จะใช้--work-tree=~/okcopy(อาจใช้พา ธ สัมพัทธ์ในขณะที่นั่งอยู่ภายใน git ทรีเดียวกันก็ใช้ได้เช่นกัน แต่วิธีนั้นอยู่ที่ความบ้าคลั่งและgit statusผลลัพธ์ใน R'lyehian)
Tom Goodfellow

10
มันทำงานได้ตามที่คาดไว้กับคอมมิตเก่าด้วยเช่นกัน (เช่นให้ SHA แทน HEAD) อย่างไรก็ตามgit statusจากนั้นก็แสดงม็อดจำนวนมาก (น่าจะเป็นเพราะตอนนี้ดัชนีตรงกับไดเร็กทอรีอื่นและไม่ใช่แผนผังงานปกติที่ไม่มีใครแตะต้อง) git resetให้กลับสู่สภาพที่ดี
Tom Goodfellow

2
เหมือนกันที่นี่git statusแสดง mods จำนวนมากและgit resetไม่ได้ช่วยอะไร ฉันต้องgit checkout -f HEADกู้คืนสถานะของ repo ของฉัน
DUzun

11
FYI: คุณต้องสร้างไดเรกทอรีด้วยตัวเองไม่เช่นนั้นคุณจะได้รับข้อผิดพลาดนี้:fatal: This operation must be run in a work tree
timaschew

13
สิ่งนี้ปรับเปลี่ยนดัชนีของโครงสร้างการทำงานหลักอย่างหายนะซึ่งโดยทั่วไปจะไม่ดี ดังที่ @TomGoodfellow แนะนำgit resetเพียงพอที่จะฟื้นฟูโครงสร้างการทำงานหลักให้มีสุขภาพดี เพื่อความปลอดภัยส่งออกไดเรกทอรีพื้นที่เก็บข้อมูลที่ SHA1 สาขาหรือแท็กใด ๆโดยไม่ต้องปรับเปลี่ยนโครงสร้างการทำงานหลักดูชาร์ลส์เบลีย์ ที่น่าอับอายgit archiveแก้ปัญหา ในทำนองเดียวกันหากต้องการชำระเงินหลายสาขาพร้อมกันอย่างปลอดภัยคำgit worktree addสั่งย่อยใหม่คือเพื่อนของคุณ
Cecil Curry

25

สำหรับไฟล์เดียว:

git show HEAD:abspath/to/file > file.copy

2
+1 และเพื่อชี้แจงเกี่ยวกับ "การกระทำก่อนหน้านี้" (แทน HEAD): หมายถึงสิ่งSHA1 IDที่สามารถพบได้ง่ายผ่านทางgitk. หากฉันเพียงต้องการ "ชำระเงิน" ไฟล์นั้นไปยังตำแหน่งชั่วคราว (เช่นไม่ย้อนกลับ) ฉันจะใช้คำshowสั่งย่อย:git show 82e54378856215ef96c5db1ff1160a741b5dcd70:MyProj/proguard/mapping.txt > myproj_mapping.txt
ef2011

19

วิธีแก้ปัญหาข้างต้นไม่ได้ผลสำหรับฉันเพราะฉันต้องการตรวจสอบเวอร์ชันที่ติดแท็กเฉพาะของต้นไม้ นั่นคือวิธีcvs exportการใช้งานโดยวิธีการ git checkout-indexไม่ใช้อาร์กิวเมนต์แท็กเนื่องจากจะตรวจสอบไฟล์จากดัชนี git checkout <tag>จะเปลี่ยนดัชนีโดยไม่คำนึงถึงโครงสร้างงานดังนั้นฉันจะต้องรีเซ็ตทรีดั้งเดิม วิธีแก้ปัญหาที่ได้ผลสำหรับฉันคือการโคลนที่เก็บ การโคลนที่ใช้ร่วมกันนั้นค่อนข้างเร็วและใช้พื้นที่ไม่มากนัก .gitไดเรกทอรีที่สามารถถอดออกได้ถ้าต้องการ

git clone --shared --no-checkout <repository> <destination>
cd <destination>
git checkout <tag>
rm -rf .git

git เวอร์ชันใหม่กว่าควรรองรับgit clone --branch <tag>การตรวจสอบแท็กที่ระบุโดยอัตโนมัติ:

git clone --shared --branch <tag> <repository> <destination>
rm -rf <destination>/.git

3
git --work-tree=/path/to/outputdir checkout <tag> -- .ไม่ได้ผลสำหรับคุณ?
warvariuc

1
ไม่มันไม่ได้ ไฟล์จริงในไดเร็กทอรีงานดั้งเดิมไม่มีการเปลี่ยนแปลง แต่เวอร์ชันที่จัดเตรียมจะสูญหายและถูกแทนที่ด้วยเวอร์ชันจากแท็ก จะไม่ดีอย่างยิ่งหากเวอร์ชันที่จัดฉากมีชุดการเปลี่ยนแปลงที่คัดสรรมาอย่างดี ฉันไม่ต้องการให้คำสั่งส่งออกแตะดัชนีช่วงเวลาของฉัน
proski

19

หากคุณกำลังทำงานภายใต้คุณลักษณะของคุณและไม่ต้องการชำระเงินกลับไปเป็นผู้เชี่ยวชาญคุณสามารถเรียกใช้:

cd ./myrepo

git worktree add ../myrepo_master master

git worktree remove ../myrepo_master

จะสร้าง../myrepo_masterไดเร็กทอรีที่มีmasterbranch commits ซึ่งคุณสามารถทำงานต่อได้


1
คำตอบที่ดีที่สุด - ง่ายและแตกต่างจากที่git --work-tree=/path/to/outputdir checkout HEAD -- .ไม่ได้ทำอะไรกับดัชนีเพียงแค่คัดลอกสาขาที่เลือกไปยังตำแหน่งที่ระบุ (ด้วยการเพิ่มไฟล์. git)
Roger Dueck

และฉันจะยกเลิกการเปลี่ยนแปลงนี้ได้อย่างไร
Scott P.

@ ScottP. just remove myrepo_masterdirectory
itsnikolay

1
การเลิกทำนี่เป็นคำสั่งย่อยจาก worktree:git worktree remove ../myrepo_master
Martijn Dashorst

8

คำตอบของเอเดรียนทำให้ "เสียชีวิต: การดำเนินการนี้ต้องดำเนินการในโครงสร้างงาน" ต่อไปนี้คือสิ่งที่เหมาะกับเรา

git worktree add <new-dir> --no-checkout --detach
cd <new-dir>
git checkout <some-ref> -- <existing-dir>

หมายเหตุ:

  • --no-checkout อย่าชำระเงินใด ๆ ใน worktree ใหม่
  • --detach อย่าสร้างสาขาใหม่สำหรับ worktree ใหม่
  • <some-ref>ทำงานร่วมกับโทษใด ๆ HEAD~1เช่นมันทำงานร่วมกับ
  • ล้างข้อมูลด้วยgit worktree prune.

+1 สำหรับการแสดงความคิดเห็นเกี่ยวกับวิธีการล้างข้อมูล - ทุกคนยินดีที่จะทำให้ repo ปัจจุบันยุ่งเหยิง เพียงตัวนี้ไม่มีผลข้างเคียง
Andrew Hill

1

นอกจากคำตอบของ @ hasen หากต้องการแสดงรายการไฟล์ที่จะชำระเงินคุณอาจต้องการใช้git ls-filesแทน find:

git ls-files -z *.txt | git checkout-index --prefix=/path-to/dest/ -f -z --stdin

ขอบคุณสำหรับการใช้งานอย่างถูกต้อง-z! ยินดีที่คุณให้สคริปต์ที่ไม่เสี่ยงต่อการโจมตีด้วยการฉีดบางประเภท
ErikE

0

ฉันกำหนดนามแฝง git เพื่อให้บรรลุสิ่งนี้ (ก่อนที่ฉันจะพบคำถามนี้)

มันเป็นฟังก์ชั่นทุบตีสั้น ๆ ที่บันทึกเส้นทางปัจจุบันเปลี่ยนไปใช้ git repo ทำการชำระเงินและกลับไปที่จุดเริ่มต้น

git checkto พัฒนา ~ / my_project_git

เช่นจะชำระเงินจากสาขาการพัฒนาไปยังไดเร็กทอรี "~ / my_project_git"

นี่คือรหัสนามแฝงภายใน~/.gitconfig:

[alias]
    checkTo = "!f(){ [ -z \"$1\" ] && echo \"Need to specify branch.\" && \
               exit 1; [ -z \"$2\" ] && echo \"Need to specify target\
               dir\" && exit 2; cDir=\"$(pwd)\"; cd \"$2\"; \
               git checkout \"$1\"; cd \"$cDir\"; };f"

0

ฉันใช้นามแฝงนี้เพื่อตรวจสอบสาขาในไดเรกทอรีชั่วคราว:

[alias]
    cot = "!TEMP=$(mktemp -d); f() { git worktree prune && git worktree add $TEMP $1 && zsh -c \"cd $TEMP; zsh\";}; f" # checkout branch in temporary directory

การใช้งาน:

git cot mybranch

จากนั้นคุณจะถูกทิ้งในเชลล์ใหม่ในไดเร็กทอรีชั่วคราวที่คุณสามารถทำงานในสาขาได้ คุณสามารถใช้คำสั่ง git ในไดเร็กทอรีนี้

เมื่อคุณทำเสร็จแล้วให้ลบไดเร็กทอรีและเรียกใช้:

git worktree prune

นอกจากนี้ยังดำเนินการโดยอัตโนมัติในนามแฝงก่อนเพิ่ม worktree ใหม่


0

ใช้git archive branch-index | tar -x -C your-folder-on-PCเพื่อโคลนสาขาไปยังโฟลเดอร์อื่น ฉันคิดว่าคุณสามารถคัดลอกไฟล์ใดก็ได้ที่คุณต้องการ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.