Git จัดการกับลิงก์สัญลักษณ์อย่างไร


1607

หากฉันมีไฟล์หรือไดเรกทอรีที่เป็นลิงก์สัญลักษณ์และฉันส่งไปยังที่เก็บ Git จะเกิดอะไรขึ้นกับมัน

ฉันจะสมมติว่ามันปล่อยให้มันเป็นลิงค์สัญลักษณ์จนกว่าไฟล์จะถูกลบแล้วถ้าคุณดึงไฟล์กลับมาจากรุ่นเก่ามันก็แค่สร้างไฟล์ปกติ

จะทำอย่างไรเมื่อฉันลบไฟล์ที่อ้างอิง? มันแค่ผูกลิงค์ห้อย?


19
.gitignoreเห็น symlink เป็นไฟล์ไม่ใช่โฟลเดอร์
0xcaff

6
เห็นได้ชัดว่ามีคำถามมากกว่าคำตอบนั้นหมายถึง ตัวอย่างเช่นฉันสงสัยในสิ่งต่อไปนี้: ถ้าฉันสร้างลิงค์ sym ในที่เก็บของฉันไปยังไฟล์ขนาดใหญ่ในที่เก็บนั้นให้กดการเปลี่ยนแปลงแล้วดึงการเปลี่ยนแปลงเหล่านั้นไปยังเครื่องอื่นจะเกิดอะไรขึ้น ไฟล์ขนาดใหญ่จะถูกจัดเก็บเป็นไฟล์ขนาดใหญ่ในทั้งสองตำแหน่งหรือจะเชื่อมโยง sym ไว้เช่นในเครื่องใหม่ไฟล์ลิงก์จะชี้ไปยังไฟล์ขนาดใหญ่ดั้งเดิมหรือไม่
jvriesem

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

6
@lasaro วิธีหลีกเลี่ยงการเชื่อมโยงที่ขาดใน repo git คือการใช้เส้นทางสัมพัทธ์เมื่อสร้าง symlink โดยใช้../..เท่าที่จำเป็น
ไวด์การ์ด

8
ขอให้สังเกตว่าใน Windows เวอร์ชั่นส่วนใหญ่คุณต้องได้รับการยกระดับเพื่อสร้าง symlink หากคุณใช้ Windows และgit pullสร้างไฟล์แทน symlink ให้ลองเรียกใช้ Git client ในฐานะผู้ดูแลระบบ
axmrnv

คำตอบ:


1348

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

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

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


328
BTW หากคุณอยู่ในระบบไฟล์เช่น FAT ที่ไม่สนับสนุนลิงก์สัญลักษณ์และที่เก็บของคุณใช้คุณสามารถตั้งcore.symlinksค่าตัวแปรการกำหนดค่าเป็นเท็จและ symlink จะถูกตรวจสอบว่าเป็นไฟล์ข้อความธรรมดาขนาดเล็กที่มีข้อความลิงค์
Jakub Narębski

14
@ JakubNarębskiฉันเห็นสิ่งนี้มาก่อน มีไฟล์ข้อความใน repo ของเราที่มีหนึ่งบรรทัดเส้นทางไปยังไลบรารีที่เราใช้ ไม่สามารถหาจุดประสงค์ของมันได้ ฉันรู้แล้วว่าเกิดอะไรขึ้น
Matt K

25
ฉันลังเลที่จะแสดงความคิดเห็นเกี่ยวกับคำตอบที่ได้รับการโหวตสูง แต่ฉันคิดว่าการใช้ถ้อยคำ "เช่นเดียวกับไฟล์ทั่วไป" อาจทำให้ผู้ใช้ใหม่เข้าใจผิด
Matthew Hannigan

10
(หมดเวลาแก้ไข) มันเหมือนไฟล์ปกติเฉพาะในเนื้อหาที่อยู่ในหยด ข้อแตกต่างที่สำคัญคือสำหรับไฟล์ปกติ blob เป็นเนื้อหาไฟล์ แต่สำหรับ symlink Blob จะมีชื่อพา ธ ของไฟล์ที่ลิงก์ไป @ JakubNarębskiเกี่ยวกับ "ไฟล์ข้อความขนาดเล็กธรรมดา" .. คุณคาดหวังว่ามันจะเล็กและข้อความ แต่แน่นอนว่า blob นั้นเป็น blob และอาจมีขนาดใหญ่และเป็นเลขฐานสอง ดูstackoverflow.com/questions/18411200/…เมื่อไฟล์นั้นพิมพ์ผิดเป็น symlink
Matthew Hannigan

2
อย่าลืมตรวจสอบการตั้งค่าส่วนกลางของคุณสำหรับ symlink และการตั้งค่า local สำหรับ symlink หากการคัดลอกการตั้งค่ามาจาก TortiseGit หรือ windows คุณอาจทำsymlinks = falseกับพวกเขาได้
phyatt

250

คุณสามารถค้นหาสิ่งที่ Git ทำกับไฟล์โดยดูว่ามันทำอะไรเมื่อคุณเพิ่มลงในดัชนี ดัชนีเป็นเหมือนการกระทำล่วงหน้า ด้วยความมุ่งมั่นของดัชนีคุณสามารถใช้git checkoutเพื่อนำทุกอย่างที่อยู่ในดัชนีกลับสู่ไดเรกทอรีการทำงาน ดังนั้น Git จะทำอย่างไรเมื่อคุณเพิ่มลิงก์สัญลักษณ์ไปยังดัชนี

หากต้องการค้นหาก่อนอื่นให้สร้างลิงก์สัญลักษณ์:

$ ln -s /path/referenced/by/symlink symlink

Git ยังไม่รู้เกี่ยวกับไฟล์นี้ git ls-filesช่วยให้คุณตรวจสอบดัชนีของคุณ ( -sพิมพ์statออกเหมือน):

$ git ls-files -s ./symlink
[nothing]

ตอนนี้เพิ่มเนื้อหาของลิงค์สัญลักษณ์ไปยังที่เก็บอ็อบเจ็กต์ Git โดยเพิ่มลงในดัชนี เมื่อคุณเพิ่มไฟล์ในดัชนี Git จะเก็บเนื้อหาไว้ในที่เก็บวัตถุ Git

$ git add ./symlink

ดังนั้นสิ่งที่เพิ่มเข้ามา?

$ git ls-files -s ./symlink
120000 1596f9db1b9610f238b78dd168ae33faa2dec15c 0       symlink

แฮชคือการอ้างอิงไปยังวัตถุที่บรรจุที่สร้างขึ้นในที่เก็บวัตถุ Git คุณสามารถตรวจสอบวัตถุนี้ถ้าคุณดูใน.git/objects/15/96f9db1b9610f238b78dd168ae33faa2dec15cรากของพื้นที่เก็บข้อมูลของคุณ นี่คือไฟล์ที่ Git เก็บในที่เก็บซึ่งคุณสามารถเช็คเอาต์ได้ในภายหลัง หากคุณตรวจสอบไฟล์นี้คุณจะเห็นว่าไฟล์มีขนาดเล็กมาก มันไม่ได้จัดเก็บเนื้อหาของไฟล์ที่เชื่อมโยง

(หมายเหตุ120000เป็นโหมดที่แสดงในls-filesเอาท์พุทมันจะคล้าย100644กับไฟล์ปกติ)

แต่ Git จะทำอะไรกับวัตถุนี้เมื่อคุณตรวจสอบจากที่เก็บและในระบบไฟล์ของคุณ? มันขึ้นอยู่กับการcore.symlinksกำหนดค่า จากman git-config:

core.symlinks

หากเป็นเท็จลิงก์สัญลักษณ์จะถูกตรวจสอบว่าเป็นไฟล์ธรรมดาขนาดเล็กที่มีข้อความลิงค์

ดังนั้นด้วยลิงก์สัญลักษณ์ในที่เก็บเมื่อทำการเช็คเอาต์คุณจะได้รับไฟล์ข้อความที่มีการอ้างอิงถึงพา ธ ระบบไฟล์แบบเต็มหรือลิงก์สัญลักษณ์ที่เหมาะสมขึ้นอยู่กับค่าของการcore.symlinksกำหนดค่า

ไม่ว่าจะด้วยวิธีใดข้อมูลที่อ้างอิงโดย symlink จะไม่ถูกเก็บไว้ในที่เก็บ


1
คำตอบที่ยอดเยี่ยม
CervEd

147

หมายเหตุ "บรรณาธิการ": โพสต์นี้อาจมีข้อมูลที่ล้าสมัย โปรดดูความคิดเห็นและคำถามเกี่ยวกับการเปลี่ยนแปลงใน Git ตั้งแต่ 1.6.1

ไดเรกทอรีที่ลิงก์:

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

ตัวอย่าง

ก่อน

 ls -l
 lrwxrwxrwx 1 admin adm   29 Sep 30 15:28 src/somedir -> /mnt/somedir

git add/commit/push

It remains the same

หลังจากgit pullและพบการปรับปรุงบางอย่าง

 drwxrwsr-x 2 admin adm 4096 Oct  2 05:54 src/somedir

4
เป็นที่น่าสังเกตว่าคำเตือนเหล่านี้เกี่ยวกับไดเรกทอรี symlinked ใช้ไม่ได้กับ symlinked รุ่น กรณีขอบหลักที่เป็นปัญหาคือผู้คนเชื่อมโยงต้นไม้การทำงานบางส่วนหรือทั้งหมดเข้าสู่เส้นทางที่แตกต่างกัน (พูดบนพาร์ติชันอื่นที่มีพื้นที่ดิสก์มากขึ้น) และคาดว่า git จะตรวจสอบรหัสผ่าน symlink ที่มีอยู่ นั่นคือถ้าคุณมีโครงการที่มี symlink เวอร์ชันไปยังไฟล์หรือไดเรกทอรีพฤติกรรม symlink-as-blob ปกติจะรักษา symlink การเปลี่ยนเวอร์ชั่นอย่างถูกต้องกับ symlink เหล่านั้นและทำงานอย่างที่คาดไว้
จอห์นวิทเลย์

พฤติกรรมข้างต้นทดสอบกับ git 1.6.5.6; แต่ฉันสงสัยอย่างยิ่งว่าพฤติกรรมเวอร์ชันนั้นถูกต้องในคอมไพล์มาระยะเวลาหนึ่งแล้ว
จอห์นวิทเลย์

22
พฤติกรรมนี้มีอยู่ใน git ทุกรุ่นหรือเคยมีการแก้ไขด้วยหรือไม่?
jbotnik

24
ดูเหมือนว่าพฤติกรรมนี้จะได้รับการแก้ไขแล้วดูที่: stackoverflow.com/a/1943656/1334781
Ron Wertlen

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