ฉันจะโคลนไดเรกทอรีย่อยของที่เก็บ Git ได้อย่างไร


1409

ฉันมีที่เก็บ Git ของฉันซึ่งที่ root มีสองไดเรกทอรีย่อย:

/finisht
/static

เมื่อเป็นเช่นนี้อยู่ในSVN , /finishtได้รับการตรวจสอบในสถานที่หนึ่งในขณะที่/staticได้รับการตรวจสอบออกอื่น ๆ เช่นดังนั้น:

svn co svn+ssh://admin@domain.com/home/admin/repos/finisht/static static

มีวิธีการทำเช่นนี้กับ Git หรือไม่?



1
สำหรับผู้ใช้ปี 2014 อะไรgit cloneคือคำสั่งที่ง่ายที่สุด? ฉันใช้นี้คำตอบง่ายๆ หากมีสิ่งที่ง่ายขึ้นโปรดแสดงความคิดเห็น
Peter Krauss

สำหรับผู้ที่พยายามโคลนเนื้อหาของพื้นที่เก็บข้อมูล (ไม่สร้างโฟลเดอร์รูท) นี่เป็นวิธีแก้ปัญหาที่ง่ายมาก: stackoverflow.com/questions/6224626/…
Marc

@JoachimBreitner: คำถามนั้นเกี่ยวกับการตรวจสอบไดเรกทอรีย่อยใน Git (ซึ่งง่าย) ในขณะที่คำถามนี้เกี่ยวกับการโคลนไดเรกทอรีย่อยใน Git (ซึ่งเป็นไปไม่ได้)
Jörg W Mittag

@NickSergeant: ในฐานะของ Git 2.19 เปิดตัว 3 สัปดาห์ที่ผ่านมาซึ่งเป็นไปได้ในที่สุดซึ่งสามารถเห็นได้ในคำตอบนี้: stackoverflow.com/a/52269934/2988พิจารณายอมรับตอนนี้ หมายเหตุ: ใน Git 2.19 จะมีการใช้งานการสนับสนุนฝั่งไคลเอ็นต์เท่านั้นการสนับสนุนฝั่งเซิร์ฟเวอร์ยังคงหายไปดังนั้นจึงสามารถใช้งานได้เมื่อทำการโคลนที่เก็บข้อมูลในเครื่องเท่านั้น นอกจากนี้โปรดทราบว่า Git hosters ขนาดใหญ่เช่น GitHub ไม่ได้ใช้เซิร์ฟเวอร์ Git จริง ๆ พวกเขาใช้การใช้งานของตัวเองดังนั้นแม้ว่าการสนับสนุนจะปรากฏในเซิร์ฟเวอร์ Git ก็ไม่ได้หมายความว่ามันทำงานบน Git hosters โดยอัตโนมัติ (OTOH พวกเขาสามารถใช้งานได้เร็วขึ้น)
Jörg W Mittag

คำตอบ:


612

แก้ไข : ในฐานะของ Git 2.19 ในที่สุดนี่ก็เป็นไปได้ดังที่เห็นได้ในคำตอบนี้

ลองพิจารณาคำตอบนั้น

หมายเหตุ: ใน Git 2.19 จะมีการใช้งานการสนับสนุนฝั่งไคลเอ็นต์เท่านั้นการสนับสนุนฝั่งเซิร์ฟเวอร์ยังคงหายไปดังนั้นจึงสามารถใช้งานได้เมื่อทำการโคลนที่เก็บข้อมูลในเครื่องเท่านั้น นอกจากนี้โปรดทราบว่า Git hosters ขนาดใหญ่เช่น GitHub ไม่ได้ใช้เซิร์ฟเวอร์ Git จริง ๆ พวกเขาใช้การดำเนินการของตัวเองดังนั้นแม้ว่าการสนับสนุนจะปรากฏในเซิร์ฟเวอร์ Git ก็ไม่ได้หมายความว่ามันทำงานบน Git hosters โดยอัตโนมัติ (OTOH เนื่องจากพวกเขาไม่ได้ใช้เซิร์ฟเวอร์ Git พวกเขาสามารถใช้งานได้เร็วขึ้นในการใช้งานของตัวเองก่อนที่จะแสดงในเซิร์ฟเวอร์ Git)


ไม่นั่นเป็นไปไม่ได้ใน Git

การดำเนินการบางอย่างเช่นนี้ใน Git จะเป็นความพยายามอย่างมากและก็หมายความว่าความสมบูรณ์ของพื้นที่เก็บข้อมูลของลูกค้าจะไม่สามารถรับประกันได้อีกต่อไป หากคุณสนใจให้ค้นหาการสนทนาใน "sparse clone" และ "sparse fetch" ในรายการส่งเมล git

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


6
คุณอาจต้องการใช้ทรีย่อยของ git แทน git submodule ทั้งนี้ขึ้นอยู่กับสถานการณ์ ดูalumnit.ca/~apenwarr/log/?m=200904#30
C Pirate

9
@StijndeWitt: checkouts เบาบางเกิดขึ้นในช่วงซึ่งเป็นเวลานานหลังจากที่git-read-tree get-fetchคำถามไม่ได้เกี่ยวกับการตรวจสอบเฉพาะไดเรกทอรีย่อย แต่เป็นเรื่องเกี่ยวกับการโคลนเฉพาะไดเรกทอรีย่อย ฉันไม่เห็นว่าการชำระเงินแบบเบาบางอาจทำเช่นนั้นได้อย่างไรgit-read-treeหลังจากทำงานหลังจากโคลนเสร็จสิ้นแล้ว
Jörg W Mittag

9
แทนที่จะ "ตอนี้" คุณต้องการให้ฉันลบคำตอบนี้หรือไม่เพื่อให้ Chronial สามารถลอยไปด้านบนได้ คุณไม่สามารถลบได้ด้วยตนเองเนื่องจากได้รับการยอมรับ แต่ผู้ดำเนินการสามารถ คุณจะรักษาชื่อเสียงที่คุณได้รับเนื่องจากมันเก่ามาก (ฉันเจอสิ่งนี้เพราะมีคนทำเครื่องหมายว่า "ลิงก์อย่างเดียว" :-)
Cody Gray

1
@CodyGray: คำตอบตามลำดับยังคงโคลนที่เก็บทั้งหมดและไม่เพียงไดเรกทอรีย่อย (ย่อหน้าสุดท้ายแม้จะระบุอย่างชัดเจน) การโคลนเฉพาะไดเรกทอรีย่อยนั้นไม่สามารถทำได้ใน Git โปรโตคอลเครือข่ายไม่รองรับรูปแบบการจัดเก็บไม่รองรับ ทุก ๆ คำตอบสำหรับคำถามนี้จะทำการโคลนพื้นที่เก็บข้อมูลทั้งหมด คำถามนี้เป็นคำถามใช่ / ไม่ใช่อย่างง่ายและคำตอบก็คือตัวละครสองตัว: ไม่เลยถ้าคำตอบของฉันยาวไม่จำเป็นไม่สั้น
Jörg W Mittag

1
@ JörgWMittag: คำตอบของ Ciro Santiliดูเหมือนจะขัดแย้งกับคุณ
Dan Dascalescu

1524

สิ่งที่คุณพยายามทำเรียกว่าเช็คเอาต์แบบเบาบางและคุณลักษณะนั้นถูกเพิ่มเข้าไปใน git 1.7.0 (กุมภาพันธ์ 2012) ขั้นตอนในการโคลนแบบเบาบางมีดังนี้:

mkdir <repo>
cd <repo>
git init
git remote add -f origin <url>

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

git config core.sparseCheckout true

ตอนนี้คุณต้องกำหนดไฟล์ / โฟลเดอร์ที่คุณต้องการตรวจสอบจริง สิ่งนี้ทำได้โดยการระบุไว้ใน.git/info/sparse-checkoutเช่น:

echo "some/dir/" >> .git/info/sparse-checkout
echo "another/sub/tree" >> .git/info/sparse-checkout

สุดท้าย แต่ไม่ท้ายสุดอัพเดต repo ที่ว่างเปล่าของคุณด้วยสถานะจากรีโมต:

git pull origin master

ตอนนี้คุณจะมีไฟล์ "เช็คเอาต์" สำหรับsome/dirและanother/sub/treeในระบบไฟล์ของคุณ (โดยที่ยังคงพา ธ ) และไม่มีพา ธ อื่นอยู่

คุณอาจต้องการที่จะมีลักษณะที่เป็นกวดวิชาขยายและคุณอาจจะอ่านอย่างเป็นทางการของเอกสารสำหรับการเช็คเอาต์เบาบาง

ในฐานะที่เป็นฟังก์ชั่น:

function git_sparse_clone() (
  rurl="$1" localdir="$2" && shift 2

  mkdir -p "$localdir"
  cd "$localdir"

  git init
  git remote add -f origin "$rurl"

  git config core.sparseCheckout true

  # Loops over remaining args
  for i; do
    echo "$i" >> .git/info/sparse-checkout
  done

  git pull origin master
)

การใช้งาน:

git_sparse_clone "http://github.com/tj/n" "./local/location" "/bin"

โปรดทราบว่านี่จะยังคงดาวน์โหลดที่เก็บข้อมูลทั้งหมดจากเซิร์ฟเวอร์ - มีเพียงการชำระเงินที่ลดขนาดเท่านั้น ในขณะนี้มันเป็นไปไม่ได้ที่จะโคลนเพียงไดเรกทอรีเดียว แต่ถ้าคุณไม่ต้องการประวัติของที่เก็บอย่างน้อยคุณสามารถประหยัดแบนด์วิดท์ได้ด้วยการสร้างโคลนตื้น ดูคำตอบของ udondanด้านล่างสำหรับข้อมูลเกี่ยวกับวิธีการรวมโคลนตื้นและเช็คเอาต์เบาบาง


ตั้งแต่ git 2.25.0 (ม.ค. 2020) คำสั่งsparse-checkoutทดลองถูกเพิ่มเข้าไปใน git:

git sparse-checkout init
# same as: 
git config core.sparseCheckout true

git sparse-checkout set "A/B"
# same as:
echo "A/B" >> .git/info/sparse-checkout

git sparse-checkout list
# same as:
cat .git/info/sparse-checkout

14
บน Apple ขอบเขต '-f' ไม่ทำงาน แค่ทำคอมไพล์ git remote remote เพิ่ม <url> โดยไม่มี -f
Anno2001

135
เป็นการปรับปรุง แต่ยังคงต้องดาวน์โหลดและเก็บสำเนาเต็มของที่เก็บระยะไกลในแหล่งกำเนิดซึ่งหนึ่งอาจต้องการหลีกเลี่ยงได้เลยถ้าเขาสนใจเฉพาะในส่วนของ codebase (หรือหากมีโฟลเดอร์ย่อยเอกสารในกรณีของฉัน )
a1an

56
มีวิธีการโคลนเนื้อหาไดเรกทอรีที่ต้องการ (ไม่ใช่ไดเรกทอรีเอง) ลงในพื้นที่เก็บข้อมูลของฉันหรือไม่? ตัวอย่างเช่นฉันต้องการเนื้อหาโคลนของhttps://github.com/Umkus/nginx-boilerplate/tree/master/srcขวาเข้า/etc/nginx
แม็ค

25
@Chronial, @ErikE: คุณทั้งคู่ถูก / ผิด: P git remote addคำสั่งไม่ได้หมายความถึงการดึง แต่git remote add -fตามที่ใช้ที่นี่แล้ว! นั่นคือความ-fหมาย
ntc2

21
การใช้สิ่งนี้และ--depth=1ฉันได้โคลน Chromium Devtools ใน 338 MB แทนที่จะเป็นประวัติ + แหล่ง Blink 4.9 GB ยอดเยี่ยม
Rudie

444

git clone --filter จาก Git 2.19

ตัวเลือกนี้จะข้ามการดึงข้อมูลวัตถุที่ไม่จำเป็นออกจากเซิร์ฟเวอร์ รวมถึง--filter=tree:0จาก Git 2.20และ--filter=combineตัวกรองคอมโพสิตที่เพิ่มเข้าไปใน Git 2.24 เราก็ได้:

git clone \
  --depth 1 \
  --filter=combine:blob:none+tree:0 \
  --no-checkout \
  "file://$(pwd)/server_repo" \
  local_repo \
;
cd local_repo
git checkout master -- mydir/

เซิร์ฟเวอร์ควรกำหนดค่าด้วย:

git config --local uploadpack.allowfilter 1
git config --local uploadpack.allowanysha1inwant 1

มีการขยายส่วนขยายไปยังโพรโทคอล Git ระยะไกลเพื่อสนับสนุนคุณสมบัตินี้v2.19.0และข้ามการดึงข้อมูลวัตถุที่ไม่ต้องการ แต่ไม่มีการสนับสนุนเซิร์ฟเวอร์ในเวลานั้น แต่สามารถทดสอบในพื้นที่ได้แล้ว

การแบ่งคำสั่ง:

รูปแบบของการจัดทำเอกสารเกี่ยวกับ--filterman git-rev-list

เอกสารบนต้นไม้ Git:

ทดสอบมันออกมา

#!/usr/bin/env bash
set -eu

list-objects() (
  git rev-list --all --objects
  echo "master commit SHA: $(git log -1 --format="%H")"
  echo "mybranch commit SHA: $(git log -1 --format="%H")"
  git ls-tree master
  git ls-tree mybranch | grep mybranch
  git ls-tree master~ | grep root
)

# Reproducibility.
export GIT_COMMITTER_NAME='a'
export GIT_COMMITTER_EMAIL='a'
export GIT_AUTHOR_NAME='a'
export GIT_AUTHOR_EMAIL='a'
export GIT_COMMITTER_DATE='2000-01-01T00:00:00+0000'
export GIT_AUTHOR_DATE='2000-01-01T00:00:00+0000'

rm -rf server_repo local_repo
mkdir server_repo
cd server_repo

# Create repo.
git init --quiet
git config --local uploadpack.allowfilter 1
git config --local uploadpack.allowanysha1inwant 1

# First commit.
# Directories present in all branches.
mkdir d1 d2
printf 'd1/a' > ./d1/a
printf 'd1/b' > ./d1/b
printf 'd2/a' > ./d2/a
printf 'd2/b' > ./d2/b
# Present only in root.
mkdir 'root'
printf 'root' > ./root/root
git add .
git commit -m 'root' --quiet

# Second commit only on master.
git rm --quiet -r ./root
mkdir 'master'
printf 'master' > ./master/master
git add .
git commit -m 'master commit' --quiet

# Second commit only on mybranch.
git checkout -b mybranch --quiet master~
git rm --quiet -r ./root
mkdir 'mybranch'
printf 'mybranch' > ./mybranch/mybranch
git add .
git commit -m 'mybranch commit' --quiet

echo "# List and identify all objects"
list-objects
echo

# Restore master.
git checkout --quiet master
cd ..

# Clone. Don't checkout for now, only .git/ dir.
git clone --depth 1 --quiet --no-checkout --filter=blob:none "file://$(pwd)/server_repo" local_repo
cd local_repo

# List missing objects from master.
echo "# Missing objects after --no-checkout"
git rev-list --all --quiet --objects --missing=print
echo

echo "# Git checkout fails without internet"
mv ../server_repo ../server_repo.off
! git checkout master
echo

echo "# Git checkout fetches the missing directory from internet"
mv ../server_repo.off ../server_repo
git checkout master -- d1/
echo

echo "# Missing objects after checking out d1"
git rev-list --all --quiet --objects --missing=print

GitHub ต้นน้ำ

ผลผลิตใน Git v2.19.0:

# List and identify all objects
c6fcdfaf2b1462f809aecdad83a186eeec00f9c1
fc5e97944480982cfc180a6d6634699921ee63ec
7251a83be9a03161acde7b71a8fda9be19f47128
62d67bce3c672fe2b9065f372726a11e57bade7e
b64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1
308150e8fddde043f3dbbb8573abb6af1df96e63 d1/a
f70a17f51b7b30fec48a32e4f19ac15e261fd1a4 d1/b
84de03c312dc741d0f2a66df7b2f168d823e122a d2
0975df9b39e23c15f63db194df7f45c76528bccb d2/a
41484c13520fcbb6e7243a26fdb1fc9405c08520 d2/b
7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master
8b25206ff90e9432f6f1a8600f87a7bd695a24af master/master
ef29f15c9a7c5417944cc09711b6a9ee51b01d89
19f7a4ca4a038aff89d803f017f76d2b66063043 mybranch
1b671b190e293aa091239b8b5e8c149411d00523 mybranch/mybranch
c3760bb1a0ece87cdbaf9a563c77a45e30a4e30e
a0234da53ec608b54813b4271fbf00ba5318b99f root
93ca1422a8da0a9effc465eccbcb17e23015542d root/root
master commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
mybranch commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
040000 tree b64bf435a3e54c5208a1b70b7bcb0fc627463a75    d1
040000 tree 84de03c312dc741d0f2a66df7b2f168d823e122a    d2
040000 tree 7d5230379e4652f1b1da7ed1e78e0b8253e03ba3    master
040000 tree 19f7a4ca4a038aff89d803f017f76d2b66063043    mybranch
040000 tree a0234da53ec608b54813b4271fbf00ba5318b99f    root

# Missing objects after --no-checkout
?f70a17f51b7b30fec48a32e4f19ac15e261fd1a4
?8b25206ff90e9432f6f1a8600f87a7bd695a24af
?41484c13520fcbb6e7243a26fdb1fc9405c08520
?0975df9b39e23c15f63db194df7f45c76528bccb
?308150e8fddde043f3dbbb8573abb6af1df96e63

# Git checkout fails without internet
fatal: '/home/ciro/bak/git/test-git-web-interface/other-test-repos/partial-clone.tmp/server_repo' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

# Git checkout fetches the missing directory from internet
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.

# Missing objects after checking out d1
?8b25206ff90e9432f6f1a8600f87a7bd695a24af
?41484c13520fcbb6e7243a26fdb1fc9405c08520
?0975df9b39e23c15f63db194df7f45c76528bccb

บทสรุป: blobs ทั้งหมดจากภายนอกd1/จะหายไป เช่น0975df9b39e23c15f63db194df7f45c76528bccbซึ่งเป็นไม่ได้หลังจากที่มีการตรวจสอบจากd2/bd1/a

โปรดทราบว่าroot/rootและmybranch/mybranchจะหายไป แต่--depth 1ซ่อนไว้จากรายการไฟล์ที่หายไป หากคุณลบไฟล์--depth 1เหล่านั้นจะปรากฏในรายการไฟล์ที่หายไป

ฉันมีความฝัน

คุณลักษณะนี้สามารถปฏิวัติ Git

ลองนึกภาพที่มีทั้งหมดฐานรหัสขององค์กรของคุณใน repo เดียวโดยไม่ต้องเครื่องมือของบุคคลที่สามที่น่าเกลียดเช่นrepo

ลองนึกภาพการจัดเก็บ blobs ขนาดใหญ่โดยตรงใน repo โดยไม่ต้องนามสกุลของบุคคลที่สามใด

ลองคิดดูว่า GitHub จะยอมให้เมตาดาต้าไฟล์ / ไดเรกทอรีเช่นดวงดาวและการอนุญาตดังนั้นคุณสามารถจัดเก็บข้อมูลส่วนตัวทั้งหมดของคุณไว้ใน repo เดียว

ลองนึกภาพถ้าsubmodules ได้รับการปฏิบัติเหมือนกับไดเรกทอรีปกติเพียงแค่ขอแผนผัง SHA และ a DNS เหมือนกลไกแก้ไขคำขอของคุณครั้งแรกมองบนท้องถิ่น~/.gitแล้วครั้งแรกไปยังเซิร์ฟเวอร์ที่ใกล้ชิด (องค์กรของกระจก / แคช) และสิ้นสุดบน GitHub


อย่างผิดปกติบน macOS กับ git เวอร์ชั่น 2.20.1 (Apple Git-117) บ่นว่า "สเปคฟิลเตอร์หลายตัวไม่สามารถรวมกันได้"
muru

1
น่าเสียดายที่ไม่มีโชคกับเวอร์ชั่น macOS git fatal: invalid filter-spec 'combine:blob:none+tree:0'ขอขอบคุณ! อาจจะใช้งานได้กับเวอร์ชันที่ใหม่กว่า
muru

1
สิ่งนี้ล้มเหลวเมื่อลองใช้งานบน Windows 10 โดยใช้ GIT 2.24.1 (ส่งตัน "ไม่สามารถอ่านไฟล์ sha1 ของ .. " + "ยกเลิกการเชื่อมโยงไฟล์ xxx ล้มเหลว") ทำงานเป็นเครื่องรางที่มีลีนุกซ์รุ่นเดียวกัน
Oyvind

1
@Ciro Santilli สิ่งนี้ยังคงล้มเหลวด้วย "ไม่สามารถอ่านไฟล์ sha1 ของ ... " ใน git เวอร์ชั่น 2.26.1.windows.1 ฉันเปิดรายงานข้อผิดพลาด: github.com/git-for-windows/git/issues/2590
nharrer

1
@nharrer ขอบคุณสำหรับข้อมูล!
Ciro Santilli 冠状病毒审查六四事件法轮功

405

คุณสามารถรวมการชำระเงินเบาบางและคุณสมบัติโคลนแบบตื้น ตื้นโคลนตัดประวัติศาสตร์และเช็คเอาท์เบาบางเพียงดึงไฟล์ที่ตรงกับรูปแบบของคุณ

git init <repo>
cd <repo>
git remote add origin <url>
git config core.sparsecheckout true
echo "finisht/*" >> .git/info/sparse-checkout
git pull --depth=1 origin master

คุณจะต้องมีคอมไพล์ขั้นต่ำ 1.9 เพื่อให้สิ่งนี้ทำงานได้ ทดสอบด้วยตนเองด้วย 2.2.0 และ 2.2.2 เท่านั้น

วิธีนี้คุณจะยังคงสามารถที่จะผลักดันgit archiveซึ่งเป็นไปไม่ได้กับ


21
สิ่งนี้มีประโยชน์และอาจเป็นคำตอบที่ดีที่สุด แต่ก็ยังคงคัดลอกเนื้อหาที่คุณไม่สนใจ (ถ้าอยู่ในสาขาที่คุณดึง) แม้ว่ามันจะไม่ปรากฏในการชำระเงินก็ตาม
สูงศักดิ์

1
เวอร์ชัน git ของคุณคืออะไร? ตามความช่วยเหลือของคอมไพล์ตัวเลือกความลึกนั้นมีให้ใช้งานหรือไม่?
udondan

2
ไม่ทำงานสำหรับฉันเมื่อคำสั่งสุดท้ายไม่ได้แต่git pull --depth=1 origin master git pull --depth=1 origin <any-other-branch>นี่แปลกมากดูคำถามของฉันที่นี่:stackoverflow.com/questions/35820630/…
Shuman

5
บน Windows บรรทัดที่สองถึงสุดท้ายจำเป็นต้องละเว้นเครื่องหมายคำพูดหรือการดึงล้มเหลว
nateirvin

4
สิ่งนี้ยังคงดาวน์โหลดข้อมูลทั้งหมด! พบโซลูชันนี้โดยใช้ svn: stackoverflow.com/a/18324458/2302437
electronix384128

157

สำหรับผู้ใช้รายอื่นที่ต้องการดาวน์โหลดไฟล์ / โฟลเดอร์จาก github เพียงใช้:

svn export <repo>/trunk/<folder>

เช่น

svn export https://github.com/lodash/lodash.com/trunk/docs

(ใช่นั่นคือ svn ที่นี่เห็นได้ชัดว่าในปี 2016 คุณยังคงต้องการ svn เพียงดาวน์โหลดไฟล์ github บางไฟล์)

มารยาท: ดาวน์โหลดโฟลเดอร์หรือไดเรกทอรีเดียวจาก GitHub repo

สำคัญ - ตรวจสอบให้แน่ใจว่าคุณอัปเดต URL github และแทนที่/tree/master/ด้วย '/ trunk /'

ในฐานะที่เป็นทุบตีสคริปต์:

git-download(){
    folder=${@/tree\/master/trunk}
    folder=${folder/blob\/master/trunk}
    svn export $folder
}

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


9
รุ่นเดียวที่ทำงานสำหรับฉันด้วย GitHub คำสั่ง git เช็กเอาต์> ไฟล์ 10k svn เอ็กซ์พอร์ตเฉพาะ 700 ที่ฉันต้องการ ขอบคุณ!
Christopher Lörken

4
พยายามทำสิ่งนี้ด้วยhttps://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/trunk/udacityแต่มีsvn: E170000: URL 'https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/trunk/udacity' doesn't existข้อผิดพลาด :(
zthomas.nc

9
@ zthomas.nc คุณต้องลบ 'ลำต้น' ก่อนหน้า udacity และแทนที่ / tree / master / ด้วย / trunk / แทน
Speedy

2
คำสั่งนี้เป็นคำสั่งที่เหมาะกับฉัน! ฉันแค่ต้องการได้รับสำเนาของไฟล์จาก repo เพื่อให้ฉันสามารถแก้ไขได้ในเครื่อง ดีเก่า SVN เพื่อช่วยเหลือ!
Michael J

3
มันใช้งานได้ แต่ดูเหมือนช้า ใช้เวลาเล็กน้อยในการเริ่มต้นและจากนั้นไฟล์จะหมุนค่อนข้างช้า
Aryeh Beitz

73

หากคุณไม่เคยวางแผนที่จะมีปฏิสัมพันธ์กับพื้นที่เก็บข้อมูลที่คุณโคลนที่คุณสามารถทำได้เต็มโคลนคอมไพล์และเขียนพื้นที่เก็บข้อมูลของคุณโดยใช้คอมไพล์กรองสาขา --subdirectory ด้วยวิธีนี้อย่างน้อยประวัติศาสตร์จะถูกเก็บรักษาไว้


11
สำหรับคนที่ไม่รู้จักคำสั่งก็คือgit filter-branch --subdirectory-filter <subdirectory>
Jaime Hablutzel

9
วิธีนี้มีข้อได้เปรียบที่ไดเรกทอรีย่อยที่คุณเลือกกลายเป็นรูทของพื้นที่เก็บข้อมูลใหม่ซึ่งเป็นสิ่งที่ฉันต้องการ
Andrew Schulman

นั่นเป็นวิธีที่ดีที่สุดและง่ายที่สุดในการใช้ นี่คือคำสั่งขั้นตอนเดียวที่ใช้ตัวกรองไดเรกทอรีย่อยgit clone https://github.com/your/repo_xx.git && cd repo_xx && git filter-branch --subdirectory-filter repo_xx_subdir
Alex

66

นี่ดูง่ายกว่า:

git archive --remote=<repo_url> <branch> <path> | tar xvf -

17
เมื่อฉันทำเช่นนี้ใน GitHub ฉันได้รับร้ายแรง: การดำเนินงานไม่ได้รับการสนับสนุนโดยโปรโตคอล สตรีมคำสั่งสิ้นสุดโดยไม่คาดคิด
Michael Fox

1
ข้อผิดพลาดของโปรโตคอลอาจเป็นเพราะ HTTPS หรือ: ใน repo url อาจเป็นเพราะไม่มีคีย์ ssh
Umair A.

2
หากคุณใช้ GitHub คุณสามารถใช้svn exportแทนได้
Milo Wielondek

2
จะไม่ทำงานด้วย Github -> คำสั่งไม่ถูกต้อง: 'git-upload-archive' xxx / yyy.git '' ดูเหมือนว่าคุณกำลังใช้ ssh เพื่อโคลน git: // ตรวจสอบให้แน่ใจว่าตัวเลือกการกำหนดค่า core.gitProxy ของคุณและตัวแปรสภาพแวดล้อม GIT_PROXY_COMMAND ไม่ได้ถูกตั้งค่า ร้ายแรง: ปลายระยะไกลวางสายโดยไม่คาดคิด
Nianliang

3
เหตุผลที่สิ่งนี้ไม่ทำงานกับ GitHub: "เราไม่สนับสนุนการใช้ git-archive เพื่อดึงไฟล์เก็บถาวรโดยตรงจาก GitHub คุณสามารถโคลน repo ภายในเครื่องและรัน git-archive หรือคลิกที่ปุ่มดาวน์โหลด ZIP บน หน้า repo " github.com/xuwupeng2000/capistrano-scm-gitcopy/issues/16
Donn Lee

63

Git 1.7.0 มี“ การจ่ายเงินน้อยมาก” โปรดดูที่“core.sparseCheckout” ในคอมไพล์ตั้งค่า manpage “เช็คเอาต์เบาบาง” ในคอมไพล์อ่านต้นไม้ manpageและ“บิตข้าม-worktree” ในคอมไพล์ปรับปรุงดัชนี manpage manpage

อินเทอร์เฟซไม่สะดวกเท่ากับของ SVN (เช่นไม่มีวิธีทำการชำระเงินแบบเบาบางในช่วงเวลาของการโคลนเริ่มต้น) แต่ฟังก์ชันพื้นฐานที่สามารถสร้างส่วนต่อประสานที่ง่ายขึ้นได้


37

เป็นไปไม่ได้ที่จะโคลนไดเรกทอรีย่อยด้วย Git เท่านั้น แต่ด้านล่างเป็นวิธีแก้ปัญหาเล็กน้อย

กรองสาขา

คุณอาจต้องการเขียนที่เก็บซ้ำเพื่อให้ดูราวกับว่าtrunk/public_html/มันเป็นรูทโครงการและทิ้งประวัติอื่น ๆ ทั้งหมด (โดยใช้filter-branch) ลองใช้สาขาชำระเงินแล้ว:

git filter-branch --subdirectory-filter trunk/public_html -- --all

หมายเหตุ: --ตัวเลือกที่แยกสาขาตัวกรองออกจากตัวเลือกการแก้ไขและ--allเพื่อเขียนสาขาและแท็กทั้งหมดใหม่ รวมถึงข้อมูลต้นฉบับทั้งหมดกระทำครั้งหรือข้อมูลผสานจะได้รับการเก็บรักษาไว้ คำสั่งนี้ให้เกียรติ.git/info/graftsไฟล์และอ้างอิงในrefs/replace/เนมสเปซดังนั้นหากคุณมีกราฟหรือการแทนที่ใด ๆ การrefsรันคำสั่งนี้จะทำให้ถาวร

คำเตือน! ประวัติที่เขียนใหม่จะมีชื่อวัตถุที่แตกต่างกันสำหรับวัตถุทั้งหมดและจะไม่มาบรรจบกับสาขาเดิม คุณจะไม่สามารถผลักดันและกระจายสาขาที่เขียนใหม่ด้านบนของสาขาดั้งเดิมได้อย่างง่ายดาย โปรดอย่าใช้คำสั่งนี้หากคุณไม่ทราบถึงความหมายที่สมบูรณ์และหลีกเลี่ยงการใช้คำสั่งนั้นหากการคอมมิทเพียงครั้งเดียวพอเพียงเพื่อแก้ไขปัญหาของคุณ


เช็คเอาต์เบาบาง

ต่อไปนี้เป็นขั้นตอนง่ายๆด้วยวิธีการชำระเงินแบบกระจัดกระจายซึ่งจะเติมไดเรกทอรีการทำงานอย่างกระจัดกระจายดังนั้นคุณสามารถบอก Git ว่ามีโฟลเดอร์หรือไฟล์ใดบ้างในไดเรกทอรีการทำงานที่ควรค่าแก่การตรวจสอบ

  1. โคลนที่เก็บตามปกติ ( --no-checkoutเป็นทางเลือก):

    git clone --no-checkout git@foo/bar.git
    cd bar
    

    คุณสามารถข้ามขั้นตอนนี้ถ้าคุณได้โคลนที่เก็บของคุณแล้ว

    คำแนะนำ: สำหรับ repos ขนาดใหญ่ให้พิจารณาตื้น ๆ โคลน ( --depth 1) เพื่อเช็คเอาต์การแก้ไขล่าสุดหรือ / --single-branchเท่านั้น

  2. เปิดใช้งานsparseCheckoutตัวเลือก:

    git config core.sparseCheckout true
    
  3. ระบุโฟลเดอร์สำหรับการชำระเงินแบบเบาบาง ( ไม่มีช่องว่างที่ท้าย):

    echo "trunk/public_html/*"> .git/info/sparse-checkout
    

    .git/info/sparse-checkoutหรือแก้ไข

  4. ชำระเงินที่สาขา (เช่นmaster):

    git checkout master
    

ตอนนี้คุณควรเลือกโฟลเดอร์ในไดเรกทอรีปัจจุบันของคุณ

คุณอาจพิจารณาลิงก์สัญลักษณ์หากคุณมีไดเรกทอรีมากเกินไปหรือกรองสาขาแทน



สาขาตัวกรองจะยังอนุญาตให้คุณpullหรือไม่
sam

2
@sam: ไม่ filter-branchจะเขียนความมุ่งมั่นของผู้ปกครองใหม่เพื่อให้พวกเขามีรหัส SHA1 ที่แตกต่างกันดังนั้นต้นไม้ที่ถูกกรองของคุณจะไม่มีข้อผูกมัดที่เหมือนกันกับต้นไม้ระยะไกล git pullจะไม่ทราบว่าจะพยายามรวมจากที่ใด
Peter Cordes

วิธีการนี้เป็นคำตอบที่น่าพอใจสำหรับกรณีของฉัน
Abbas

10

ฉันเพิ่งเขียนสคริปต์สำหรับGitHub GitHub

การใช้งาน:

python get_git_sub_dir.py path/to/sub/dir <RECURSIVE>

11
FYI นั่นสำหรับGitHubเท่านั้น
Sz.

9
และเห็นได้ชัดว่านี่คือการดาวน์โหลดไดเรกทอรีไม่ใช่การคัดลอกชิ้นส่วน repo ที่มีข้อมูลเมตาทั้งหมด ... ใช่ไหม
LarsH

5
คุณควรรวมรหัสของคุณไว้ที่นี่และไม่ควรอยู่ที่อื่น
jww

urllib2.HTTPError: HTTP Error 403: เกินขีด จำกัด อัตรา
diyism

9

การทำเช่นนี้จะโคลนโฟลเดอร์เฉพาะและลบประวัติทั้งหมดที่ไม่เกี่ยวข้อง

git clone --single-branch -b {branch} git@github.com:{user}/{repo}.git
git filter-branch --subdirectory-filter {path/to/folder} HEAD
git remote remove origin
git remote add origin git@github.com:{user}/{new-repo}.git
git push -u origin master

นี่คือมังกร คุณจะได้รับการต้อนรับจากคำเตือน: คอมไพล์กรองสาขามีจำนวนที่มากเกินไปของ gotchas สร้างประวัติศาสตร์เขียนใหม่แหลกเหลว .. จากนั้นเอกสาร git-filter-branchมีรายการคำเตือนที่ค่อนข้างยาว
Oyvind

6

นี่คือเชลล์สคริปที่ฉันเขียนสำหรับกรณีการใช้งานของการเช็คเอาต์ย่อยไดเรกทอรีย่อย

coSubDir.sh

localRepo=$1
remoteRepo=$2
subDir=$3


# Create local repository for subdirectory checkout, make it hidden to avoid having to drill down to the subfolder
mkdir ./.$localRepo
cd ./.$localRepo
git init
git remote add -f origin $remoteRepo
git config core.sparseCheckout true

# Add the subdirectory of interest to the sparse checkout.
echo $subDir >> .git/info/sparse-checkout

git pull origin master

# Create convenience symlink to the subdirectory of interest
cd ..
ln -s ./.$localRepo/$subDir $localRepo

2
สคริปต์ที่ดีมีเพียงสิ่งเดียวเท่านั้นที่ควรได้รับการแก้ไขคือ symlink ควร ln -s ./.$localRepo/$subDir $localRepoแทนที่ln -s ./.$localRepo$subDir $localRepo
valentin_nasta

2

ฉันเขียน .gitconfig [alias]เพื่อดำเนินการ "เช็คเอาต์เบาบาง" ลองดู (ไม่มีการเล่นสำนวนเจตนา):

ใน Windows ทำงาน cmd.exe

git config --global alias.sparse-checkout "!f(){ [ $# -eq 2 ] && L=${1##*/} L=${L%.git} || L=$2; mkdir -p \"$L/.git/info\" && cd \"$L\" && git init --template= && git remote add origin \"$1\" && git config core.sparseCheckout 1; [ $# -eq 2 ] && echo \"$2\" >> .git/info/sparse-checkout || { shift 2; for i; do echo $i >> .git/info/sparse-checkout; done }; git pull --depth 1 origin master;};f"

มิฉะนั้น:

git config --global alias.sparse-checkout '!f(){ [ $# -eq 2 ] && L=${1##*/} L=${L%.git} || L=$2; mkdir -p "$L/.git/info" && cd "$L" && git init --template= && git remote add origin "$1" && git config core.sparseCheckout 1; [ $# -eq 2 ] && echo "$2" >> .git/info/sparse-checkout || { shift 2; for i; do echo $i >> .git/info/sparse-checkout; done }; git pull --depth 1 origin master;};f'

การใช้งาน :

# Makes a directory ForStackExchange with Plug checked out
git sparse-checkout https://github.com/YenForYang/ForStackExchange Plug

# To do more than 1 directory, you have to specify the local directory:
git sparse-checkout https://github.com/YenForYang/ForStackExchange ForStackExchange Plug Folder

git configคำสั่งที่มี 'minified' เพื่ออำนวยความสะดวกและการเก็บรักษา แต่นี่คือนามแฝงขยาย:

# Note the --template= is for disabling templates.
# Feel free to remove it if you don't have issues with them (like I did)
# `mkdir` makes the .git/info directory ahead of time, as I've found it missing sometimes for some reason
f(){
    [ "$#" -eq 2 ] && L="${1##*/}" L=${L%.git} || L=$2;
    mkdir -p "$L/.git/info"
        && cd "$L"
        && git init --template=
        && git remote add origin "$1"
        && git config core.sparseCheckout 1;
    [ "$#" -eq 2 ]
        && echo "$2" >> .git/info/sparse-checkout
        || {
            shift 2;
            for i; do
                echo $i >> .git/info/sparse-checkout;
            done
        };
    git pull --depth 1 origin master;
};
f

ทำไมงานนี้: L=${1##*/} L=${L%.git}? ที่ว่างเป็นตัวดำเนินการหรือไม่
Gulzt

2

ใช้ Linux หรือไม่ และต้องการเพียงแค่ต้นไม้ที่เข้าถึงได้ง่ายและทำความสะอาดหรือไม่ โดยไม่รบกวนรหัสที่เหลือในเครื่องของคุณ ลองsymlink !

git clone https://github.com:{user}/{repo}.git ~/my-project
ln -s ~/my-project/my-subfolder ~/Desktop/my-subfolder

ทดสอบ

cd ~/Desktop/my-subfolder
git status

1

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

ให้ไว้:ที่เก็บ git ที่มีอยู่, เช่นgit@github.com:some-user/full-repo.git, มีหนึ่งหรือมากกว่าหนึ่งไดเรกทอรีที่คุณต้องการที่จะดึงเป็นอิสระจากส่วนที่เหลือของ repo, เช่นไดเรกทอรีชื่อapp1และapp2

สมมติว่าคุณมีที่เก็บคอมไพล์เป็นด้านบน ...

จากนั้นคุณสามารถเรียกใช้ขั้นตอนเช่นต่อไปนี้เพื่อดึงเพียงไดเรกทอรีที่เฉพาะเจาะจงจาก repo ขนาดใหญ่:

mkdir app1
cd app1
git init
git remote add origin git@github.com:some-user/full-repo.git
git config core.sparsecheckout true
echo "app1/" >> .git/info/sparse-checkout
git pull origin master

ฉันคิดผิดพลาดว่าจะต้องตั้งค่าตัวเลือกการกระจัดกระจายในที่เก็บต้นฉบับ: นี่ไม่ใช่กรณี คุณกำหนดไดเรกทอรีที่คุณต้องการภายในก่อนที่จะดึงจากระยะไกล หวังว่าคำอธิบายนี้จะช่วยคนอื่น


0

ในขณะที่ฉันเกลียดจริง ๆ ต้องใช้ svn เมื่อจัดการกับ repos git: / ฉันใช้มันตลอดเวลา;

function git-scp() (
  URL="$1" && shift 1
  svn export ${URL/blob\/master/trunk}
)

สิ่งนี้ช่วยให้คุณสามารถคัดลอกออกจาก URL Github โดยไม่ต้องแก้ไข การใช้งาน;

--- /tmp » git-scp https://github.com/dgraph-io/dgraph/blob/master/contrib/config/kubernetes/helm                                                                                                                  1 ↵
A    helm
A    helm/Chart.yaml
A    helm/README.md
A    helm/values.yaml
Exported revision 6367.

--- /tmp » ls | grep helm
Permissions Size User    Date Modified    Name
drwxr-xr-x     - anthony 2020-01-07 15:53 helm/

0

หากคุณเพิ่งสนใจที่จะแก้ไขไฟล์ล่าสุดของไดเรกทอรี Github ให้คุณดาวน์โหลดที่เก็บเป็นไฟล์ Zip ซึ่งไม่มีประวัติ ดังนั้นการดาวน์โหลดจึงเร็วกว่ามาก


0

ดังนั้นฉันจึงลองทุกอย่างในดอกยางนี้และไม่มีอะไรที่เหมาะกับฉัน ... ปรากฎว่าในรุ่น 2.24 ของ Git (อันที่มาพร้อมกับ cpanel ในเวลาที่ตอบคำถามนี้) คุณไม่จำเป็นต้องทำสิ่งนี้

echo "wpm/*" >> .git/info/sparse-checkout

เพียงคุณมีชื่อโฟลเดอร์

wpm/*

ดังนั้นในระยะสั้นคุณทำเช่นนี้

git config core.sparsecheckout true

จากนั้นคุณแก้ไข. git / info / sparse-checkout และเพิ่มชื่อโฟลเดอร์ (หนึ่งรายการต่อบรรทัด) ด้วย / * ที่ท้ายเพื่อรับโฟลเดอร์ย่อยและไฟล์

wpm/*

บันทึกและเรียกใช้คำสั่งเช็คเอาต์

git checkout master

ผลที่ได้คือโฟลเดอร์ที่คาดหวังจาก repo ของฉันและไม่มีอะไรอื่นโหวตขึ้นถ้าสิ่งนี้เหมาะกับคุณ

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