ฉันจะทำให้ Git ติดตาม symlinks ได้อย่างไร


217

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

PS: ฉันรู้ว่ามันไม่ปลอดภัยมาก แต่ฉันต้องการทำในบางกรณีเท่านั้น


5
มีข้อเสียในการใช้ฮาร์ดลิงก์สำหรับสิ่งนี้หรือไม่?
Ehtesh Choudhury

12
ด้วย Windows 7 "mklink / d" (ลิงก์สัญลักษณ์ไดเรกทอรี) ไม่สามารถใช้งานได้กับ git แต่ "mklink / j" (juction) ทำงานได้ดี
yoyo

1
หากไฟล์ถูกสร้างอัตโนมัติโดยแอปพลิเคชันที่สร้างใหม่ในลักษณะที่จะลบไฟล์และสร้างไฟล์ขึ้นใหม่ใช่แล้วนี่เป็นปัญหาที่ฮาร์ดลิงก์ไปยังไฟล์จะไม่สามารถแก้ไขได้
Martin Pecka

1
@EhteshChoudhury คุณไม่สามารถสร้างลิงก์ที่ยากสำหรับไดเรกทอรีได้
Gaurav Kansal

คำตอบ:


46

หมายเหตุ:คำแนะนำนี้ล้าสมัยไปแล้วตามความคิดเห็นตั้งแต่ Git 1.6.1 Git เคยทำตัวแบบนี้และไม่ทำอีกต่อไป


Git ตามค่าเริ่มต้นพยายามจัดเก็บ symlink แทนที่จะติดตามพวกเขา (เพื่อความกะทัดรัดและโดยทั่วไปเป็นสิ่งที่ผู้คนต้องการ)

อย่างไรก็ตามฉันตั้งใจจัดการให้เพิ่มไฟล์เกิน symlink เมื่อ symlink เป็นไดเรกทอรี

เช่น:

  /foo/
  /foo/baz
  /bar/foo --> /foo
  /bar/foo/baz

จากการทำ

 git add /bar/foo/baz

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


72
คอมมิชชัน 725b06050a083474e240a2436121e0a80bb9f175 และ 806d13b1ccdbdde4bbdfb96b24f2491224241212ee ดังนั้นจึงไม่สามารถใช้งานได้ในเวอร์ชันของ git ตั้งแต่ 1.6.1
มาร์กยาว

1
$ git เพิ่ม src / main / path / ConvertSymlinkToDir เสียชีวิต: 'src / main / path / ConvertSymlinkToDir' อยู่นอกเหนือการเชื่อมโยงสัญลักษณ์
user1767316

2
@ user1767316 อ่านทุกสิ่งและความคิดเห็น มันเคยทำงานมันไม่ได้อีกต่อไป การเปลี่ยนแปลงซอฟต์แวร์ แต่คำตอบที่ยอมรับไม่ได้ ฉันชี้แจงว่าวิธีนี้ใช้ไม่ได้ ดูคำตอบอื่น
Kent Fredric

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

144

สิ่งที่ฉันทำเพื่อเพิ่มรับไฟล์ภายใน symlink ใน Git (ฉันไม่ได้ใช้ symlink แต่):

sudo mount --bind SOURCEDIRECTORY TARGETDIRECTORY

ทำคำสั่งนี้ในไดเรกทอรีที่จัดการโดย Git TARGETDIRECTORYจะต้องสร้างขึ้นก่อนที่SOURCEDIRECTORYจะติดตั้งเข้าไป

มันใช้งานได้ดีบน Linux แต่ไม่ใช่ใน OS X! เคล็ดลับนั้นช่วยฉันด้วยการโค่นล้มเช่นกัน ฉันใช้มันเพื่อรวมไฟล์จากบัญชี Dropbox ซึ่งผู้ออกแบบเว็บทำหน้าที่ของเขา / เธอ


8
จะเป็นวิธีที่ดีมากถ้าไม่จำเป็นต้องใช้ sudo
MestreLion

13
umount [mydir]หากต้องการยกเลิกการนี้มีผลผูกพันใช้ (+1 สำหรับเคล็ดลับที่ยอดเยี่ยมของคุณ @ user252400)
JellicleCat

10
ใช้งานได้เฉพาะในระหว่างเซสชัน วิธีที่ดีที่สุดที่จะทำให้ "นิรันดร์" คืออะไร?
Adobe

17
@Adobe: ใส่ไว้ใน / etc / fstab เช่นนั้น: / sourcedir / targetdir ไม่มีการผูก
Alexander Garden

8
sshfs สามารถบรรลุเคล็ดลับแบบนั้นได้โดยไม่ต้องใช้ sudo ที่นี่
PypeBros

75

ทำไมไม่สร้าง symlink แบบอื่น ๆ ล่ะ? ความหมายแทนที่จะเชื่อมโยงจากที่เก็บ Git ไปยังไดเรกทอรีแอปพลิเคชันเพียงเชื่อมโยงวิธีอื่น ๆ

ตัวอย่างเช่นสมมติว่าฉันกำลังติดตั้งแอปพลิเคชัน~/applicationที่ต้องใช้ไฟล์กำหนดค่าconfig.conf:

  • ฉันเพิ่มconfig.confไปยังที่เก็บ Git ของฉันตัวอย่างเช่นที่~/repos/application/config.confฉันสำหรับตัวอย่างเช่นที่
  • แล้วฉันจะสร้าง symlink จากจากการทำงาน~/application ln -s ~/repos/application/config.conf

วิธีนี้อาจไม่ได้ผลเสมอไป แต่มันก็ใช้ได้ดีสำหรับฉันจนถึงตอนนี้


5
ดูเหมือนจะเป็นวิธีเดียวและก็ไม่เลวเลย ... ฉันคิดว่าคุณเป็นวิธีที่สง่างาม git ติดตามเนื้อหาไม่ใช่ไฟล์ ดังนั้นการรักษาเนื้อหาทั้งหมดเข้าด้วยกันและเชื่อมโยงจากที่อื่นไปยังที่อื่น ๆ จึงเหมาะสม
MestreLion

12
ในกรณีของฉันฉันต้องการลิงก์จาก repo git หนึ่งไปอีกอันหนึ่งดังนั้นฉันสามารถแก้ไขไฟล์ในตำแหน่งใดตำแหน่งหนึ่ง บน Windows 7 ทางแยก ("mklink / j") ทำเคล็ดลับ
yoyo

3
แน่นอน. บางครั้งคำตอบนั้นง่ายมาก
BBW ก่อน

ถ้าคุณต้องการคอมไพล์ทั้งต้นทางและปลายทาง? (เพราะทั้งคู่เป็นรหัสที่แตกต่างกันที่คุณต้องการให้มีในที่เก็บที่แตกต่างกัน)
DrGC

1
ไม่ตอบคำถาม :( ฉันต้องการให้ส่วนหนึ่งของที่เก็บข้อมูลของฉันถูกซิงค์ใน iCloud ของฉันโชคไม่ดีที่ iCloud ไม่ได้ติดตาม symlinks ดังนั้นฉันคิดว่าฉันอาจสร้างคอมไพล์ git ตามด้วย symlink และเก็บไฟล์ต้นฉบับใน iCloud symlinks: \
Jerry Green

49

ใช้ฮาร์ดลิงก์แทน สิ่งนี้แตกต่างจากลิงก์แบบนุ่ม (สัญลักษณ์) โปรแกรมทั้งหมดรวมถึงgitจะถือว่าไฟล์เป็นไฟล์ปกติ โปรดทราบว่าเนื้อหาสามารถแก้ไขได้โดยการเปลี่ยนทั้งแหล่งที่มาหรือปลายทาง

บน macOS (ก่อนหน้า 10.13 High Sierra)

หากคุณมีคอมไพล์และ Xcode ติดตั้งติดตั้ง Hardlink มันเป็นกล้องจุลทรรศน์เครื่องมือในการสร้างความเชื่อมโยงอย่างหนัก

หากต้องการสร้างฮาร์ดลิงก์เพียงแค่:

hln source destination

การอัพเดต macOS High Sierra

Apple File System สนับสนุนลิงก์ฮาร์ดไดรฟ์หรือไม่

ระบบไฟล์ Apple ไม่รองรับลิงก์ฮาร์ดไดรฟ์ ลิงก์ฮาร์ดไดเรคทอรีทั้งหมดจะถูกแปลงเป็นลิงก์สัญลักษณ์หรือชื่อแทนเมื่อคุณแปลงจากรูปแบบปริมาณ HFS + เป็น APFS บน macOS

จากAPFS คำถามที่พบบ่อยบน developer.apple.com

ติดตามhttps://github.com/selkhateeb/hardlink/issues/31เพื่อหาทางเลือกอื่นในอนาคต

บน Linux และ Unix รสชาติอื่น ๆ

lnคำสั่งสามารถทำให้เชื่อมโยงอย่างหนัก:

ln source destination

บน Windows (Vista, 7, 8, …)

มีคนแนะนำให้ใช้mklinkสร้าง junction บน Windows แต่ฉันยังไม่ได้ลอง:

mklink /j "source" "destination"

7
เพียงแค่ทราบ: นี่เป็นสิ่งที่ฉันกำลังมองหา แต่แล้วฉันได้เรียนรู้ว่าบนลินุกซ์ฮาร์ดลิ้งค์ไม่สามารถข้ามขอบเขตของระบบไฟล์ (ซึ่งเป็นกรณีการใช้งานของฉัน)
sdaau

26
คุณไม่สามารถ hardlink ไปยังไดเรกทอรีได้ไหม
Nanne

1
ln source destinationทำงานใน OS X ได้เช่นกัน ทดสอบกับ El Capitan
Mahdi Dibaiee

7
@Nanne ไม่มี cp -al source destinationแต่คุณสามารถทำได้: `-l 'หมายถึงไฟล์ฮาร์ดลิงก์แทนที่จะคัดลอก
เปาโล

6
น่าเสียดายที่คุณไม่สามารถเชื่อมโยงไดเรกทอรีฮาร์ดไดรฟ์หรือข้ามขอบเขตระบบไฟล์ นี่ทำให้โซลูชันนี้ไม่สามารถใช้งานได้สองเท่าสำหรับฉัน
Konrad Rudolph

25

นี่คือเบ็ดกระทำก่อนหน้าซึ่งแทนที่ Blogs symlink ในดัชนีโดยมีเนื้อหาของ symlink เหล่านั้น

ใส่สิ่งนี้ลงใน.git/hooks/pre-commitและทำให้มันปฏิบัติได้:

#!/bin/sh
# (replace "find ." with "find ./<path>" below, to work with only specific paths)

# (these lines are really all one line, on multiple lines for clarity)
# ...find symlinks which do not dereference to directories...
find . -type l -exec test '!' -d {} ';' -print -exec sh -c \
# ...remove the symlink blob, and add the content diff, to the index/cache
    'git rm --cached "$1"; diff -au /dev/null "$1" | git apply --cached -p1 -' \
# ...and call out to "sh".
    "process_links_to_nondir" {} ';'

# the end

หมายเหตุ

เราใช้ฟังก์ชั่นที่สอดคล้องกับ POSIX ให้มากที่สุด อย่างไรก็ตามdiff -aไม่เป็นไปตาม POSIX อาจเป็นไปในหมู่สิ่งอื่น ๆ

อาจมีข้อผิดพลาด / ข้อผิดพลาดบางอย่างในรหัสนี้แม้ว่าจะมีการทดสอบบ้าง


4
เป็นเรื่องดีที่ได้เห็นความพยายามในการตอบคำถามจริง ๆ เกี่ยวกับไฟล์ไม่ใช่ไดเรกทอรี อย่างไรก็ตามโปรดทราบว่าไฟล์ข้างต้นจะยังคงปรากฏtypechangeในgit statusไฟล์ซึ่งเป็น symlink จริง แต่ตอนนี้สิ่งที่พวกเขาไม่ได้เป็นคอมไพล์
David Fraser

1
ขอบคุณสำหรับสิ่งนี้; แค่อยากรู้ว่าอะไรคือprocess_links_to_nondirอะไร?
sdaau

@sdaau มันเป็นชื่อ / argv[0]ซึ่งใช้เป็นชื่อคำสั่งสำหรับshกระบวนการ (เอาฉันสักเล็กน้อยที่จะคิดออกเพราะฉันจำไม่ได้ว่ามันคืออะไรทั้ง☺😃)
Abbafei

3
@Abbafei คุณสามารถแก้ไขสคริปต์เพื่อให้ทำงานบน Ubuntu (14.04) ได้หรือไม่ find: missing argument to -exec'มันมีการแสดง อาจจำเป็นต้องใช้คำสั่งทีละขั้นตอนแทนการไพพ์ & รวมทุกอย่างไว้ในบรรทัดเดียว
Khurshid Alam

1
@KhurshidAlam สำหรับฉันมันทำงานเพื่อลบบรรทัดที่คอมเม้นต์ระหว่างบรรทัดคำสั่ง อย่างไรก็ตามตะขอไม่ทำงานตามที่คาดไว้ (ฉันได้รับtypechangeเช่น @DavidFraser แต่ไฟล์ที่เชื่อมโยงดูเหมือนว่าจะไม่ได้รับการจัดฉากอีกต่อไป)
Scz

14

เมื่อวันที่MacOS(ฉันมีซ้อม / 10.14, gitรุ่น 2.7.1) bindfsการใช้งาน

brew install bindfs

cd /path/to/git_controlled_dir

mkdir local_copy_dir

bindfs </full/path/to/source_dir> </full/path/to/local_copy_dir>

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


ดูดีมากสำหรับทีมที่ทำงานบน mac os ฉันคิดว่าฮาร์ดลิงก์ที่แสดงด้านล่างควรใช้กับ windows และ linux
Devin G Rhode

สิ่งนี้มีประโยชน์และฉันคิดว่าทางออกที่ดีที่สุดสำหรับความสามารถที่มีประโยชน์ แต่ขาดหายไปใน MacOS โปรดทราบว่าฉันได้รับFailed to resolve... No such file or directoryข้อผิดพลาดยกเว้นว่าฉันใช้ชื่อพา ธ แบบเต็มกับbindfsคำสั่ง
electromaggot

ขอบคุณ @electromaggot เพิ่มการชี้แจงว่าจำเป็นต้องใช้เส้นทางแบบเต็ม
ijoseph

1
ใช้งานได้ดีบน Macos Catalina!
Jerry Green

13

ฉันเคยเพิ่มไฟล์เกิน symlink มาซักพักแล้ว สิ่งนี้เคยทำงานได้ดีโดยไม่ต้องมีการเตรียมการพิเศษ ตั้งแต่ฉันอัปเดตเป็น Git 1.6.1 สิ่งนี้ไม่ทำงานอีกต่อไป

คุณอาจเปลี่ยนไปใช้ Git 1.6.0 เพื่อทำงานนี้ได้ ฉันหวังว่า Git รุ่นอนาคตจะมีการตั้งค่าสถานะเพื่อgit-addให้สามารถติดตาม symlink ได้อีกครั้ง


12

ฉันเบื่อกับการแก้ปัญหาทุกอย่างในที่นี้ไม่ว่าจะล้าสมัยหรือต้องการรูทดังนั้นฉันจึงสร้างโซลูชันที่ใช้ LD_PRELOAD (Linux เท่านั้น)

มันเชื่อมโยงกับภายในของ Git โดยเอาชนะ 'นี่คือ symlink หรือไม่' ฟังก์ชั่นช่วยให้ symlink จะถือว่าเป็นเนื้อหาของพวกเขา ตามค่าเริ่มต้นลิงก์ทั้งหมดไปยังนอก repo จะถูกขีดเส้นใต้ ดูลิงค์สำหรับรายละเอียด


โซลูชั่นที่สร้างสรรค์มากที่ใช้LD_PRELOADเพื่อแทนที่ฟังก์ชั่นห้องสมุด!
iBug

ใช่ แต่มันควรจะทำอย่างละเอียดที่นี่ คุณสามารถทำได้ไหม?
Peter Mortensen

ไม่แน่ใจว่าจะช่วยให้รายละเอียดมากน้อยเพียงใด เว้นแต่ฉันจะคัดลอกซอร์สโค้ดทั้งหมดคำตอบนี้จะขึ้นอยู่กับลิงก์นั้นเสมอซึ่งจะพบ readme ได้เช่นกัน แต่ใช่ฉันเดาว่าฉันสามารถจำลองส่วนสำคัญของ readme ได้
Alcaro

สิ่งนี้ไม่ได้รวบรวมบน OS X (Mojave 10.14.2) รับข้อผิดพลาดสี่ข้อที่บ่นเกี่ยวกับ 'strchrnul' (คุณหมายถึง 'strchr' หรือไม่) และอีกข้อหนึ่งเกี่ยวกับ '__xstat64' (คุณหมายถึง '__lxstat64' หรือไม่) ในที่สุดฉันก็ได้รับ "การเข้าถึงสมาชิกในข้อผิดพลาด 'dirent64' ประเภทที่ไม่สมบูรณ์ เกิดขึ้นไม่ว่าฉันจะใช้ "make", "make OPT = 1" หรือ "sh install.sh"
Erik Veland

@ErikVeland ฉันลองใช้เล็กน้อย แต่ดูเหมือนว่า OSX ไม่รองรับ LD_PRELOAD หรืออะไรทำนองนั้น เอกสารต่าง ๆ แนะนำสิ่งต่าง ๆ แต่พวกเขามีอายุหลายปีและ Apple รักสิ่งที่คัดค้าน ฉันไม่สามารถทำงานใด ๆ ได้ ขอโทษ
Alcaro

6

ด้วย Git 2.3.2+ (ไตรมาสที่ 1 ปี 2558) มีอีกกรณีหนึ่งที่ Git จะไม่ติดตาม symlink อีกต่อไป: ดูคอมมิชชัน e0d201bโดยJunio ​​C Hamano ( gitster) (ผู้ดูแล Git หลัก)

apply: ห้ามสัมผัสไฟล์ใด ๆ นอกเหนือจากลิงก์สัญลักษณ์

เนื่องจาก Git ติดตามลิงก์สัญลักษณ์เป็นลิงก์สัญลักษณ์พา ธ ที่มีลิงก์สัญลักษณ์ในส่วนนำของมัน (เช่นpath/to/dir/fileที่ไหนpath/to/dirลิงก์สัญลักษณ์ไปยังที่อื่นไม่ว่าจะเป็นภายในหรือภายนอกต้นไม้ทำงาน) จะไม่ปรากฏในแพทช์ที่ใช้งานได้อย่างถูกต้อง ยกเว้นในกรณีที่แพทช์เดียวกันเอาลิงค์สัญลักษณ์ออกก่อนเพื่อให้สามารถสร้างไดเรกทอรีได้

ตรวจจับและปฏิเสธแพตช์ดังกล่าว

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

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

ด้วยวิธีนี้เรา:

  • รับความเสียหายหรือความผิดพลาดในการเพิ่มลิงค์สัญลักษณ์path/to/dirและไฟล์path/to/dir/fileในเวลาเดียวกัน
  • ขณะที่ช่วยให้แพทช์ที่ถูกต้องที่เอาสัญลักษณ์แล้วเพิ่มไฟล์link path/to/dirpath/to/dir/file

ซึ่งหมายความว่าในกรณีนั้นข้อความแสดงข้อผิดพลาดจะไม่เหมือนกับสิ่งทั่วไป"%s: patch does not apply"แต่เป็นข้อความที่เฉพาะเจาะจงมากขึ้น:

affected file '%s' is beyond a symbolic link

4

อืมmount --bindดูเหมือนจะไม่ทำงานกับดาร์วิน

ไม่มีใครมีเคล็ดลับที่จะ?

[แก้ไข]

ตกลงฉันพบคำตอบใน Mac OS X คือการสร้างการเชื่อมโยง ยกเว้นว่า API นั้นจะไม่ถูกเปิดเผยผ่านlnดังนั้นคุณต้องใช้โปรแกรมเล็ก ๆ ของคุณเองเพื่อทำสิ่งนี้ นี่คือลิงค์ไปยังโปรแกรมนั้น:

การสร้างลิงก์ฮาร์ดไดรฟ์ใน Mac OS X

สนุก!


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

4
คุณสามารถทำได้ผ่านcode.google.com/p/bindfsซึ่งสามารถติดตั้งได้โดยใช้พอร์ต
Kit Sunde

0

ฉันใช้ Git 1.5.4.3 และมันกำลังติดตาม symlink ที่ผ่านมาหากมีเครื่องหมายทับ เช่น

# Adds the symlink itself
$ git add symlink

# Follows symlink and adds the denoted directory's contents
$ git add symlink/

5
อย่างน้อยใน OSX ผลลัพธ์นี้ในfatal: 'src/' is beyond a symbolic link
Dan Rosenstark

2
ตามที่อธิบายไว้โดย @Mark Longair สิ่งนี้จะใช้ได้จนถึง git 1.6.1
MestreLion

นั่นคือปัญหาของฉันขอบคุณ!
Mike Q

0

การแปลงจาก symlink อาจมีประโยชน์ การเชื่อมโยงในโฟลเดอร์ Git แทนลิงก์สัญลักษณ์โดยสคริปต์


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