Git และฮาร์ดลิงก์


98

เมื่อพิจารณาว่า Git ไม่รู้จักลิงก์สัญลักษณ์ที่ชี้นอกที่เก็บมีปัญหาในการใช้ฮาร์ดลิงก์หรือไม่

Git สามารถทำลายพวกเขาได้หรือไม่? คุณช่วยชี้ข้อมูลโดยละเอียดให้ฉันได้ไหม


2
คุณกำลังพยายามทำอะไรและทำไม? ฮาร์ดลิงค์ไม่ต่างจากไฟล์ปกติ หากคุณเคยดึงเวอร์ชันใหม่จากที่เก็บอื่นเวอร์ชันนั้นจะเขียนทับเวอร์ชันที่คุณมี - อะไรคือจุดเชื่อมโยงกับบางสิ่งที่อยู่นอก repo
Carl Norum

2
Git จะรับรู้ symlink ที่ชี้ไปยังพา ธ ภายนอกที่เก็บ
mipadi

ไม่มี mipadi วิธีเดียวคือโบกไฟล์ใน repo และลิงก์ symjbolic ในตำแหน่ง "จริง"
Alfredo Palhares

คำตอบ:


89

อ็อบเจ็กต์ 'tree' ซึ่งแสดงถึงไดเร็กทอรีใน Git เก็บชื่อไฟล์และสิทธิ์ (ส่วนย่อย) ไม่เก็บหมายเลขไอโหนด (หรือรหัสไฟล์ประเภทอื่น ๆ ) ดังนั้นจึงไม่สามารถแสดงฮาร์ดลิงก์ ในคอมไพล์ได้อย่างน้อยก็ไม่มีเครื่องมือของบุคคลที่สามเช่นmetastoreหรือgit-cache-meta (และฉันไม่แน่ใจว่าจะเป็นไปได้หรือไม่แม้จะมีเครื่องมือเหล่านั้นก็ตาม)

Git พยายามที่จะไม่แตะต้องไฟล์ที่ไม่จำเป็นต้องอัปเดต แต่คุณต้องคำนึงว่า git ไม่ได้พยายามรักษาฮาร์ดลิงก์ดังนั้น git จึงอาจถูกทำลายได้


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


4
Symlinks ไปยังพา ธ นอก repo จะมีประโยชน์ ฉันใช้มันในเว็บแอพเพื่อชี้ไปที่ฐานข้อมูลหรือไฟล์สื่อที่ repo ไม่ติดตาม ด้วยวิธีนี้ไฟล์กำหนดค่าของเว็บแอปสามารถชี้ไปยังเส้นทางแบบคงที่ แต่ตำแหน่งจริงของเส้นทางนั้นอาจแตกต่างกันไประหว่างการพัฒนาในพื้นที่และสภาพแวดล้อมเซิร์ฟเวอร์
mipadi

@mipadi: BTW. gitweb สมัยใหม่มีกรณีพิเศษสำหรับการแสดง symlink ที่นำหน้าหลังการทำให้เป็นมาตรฐานภายนอกที่เก็บ
Jakub Narębski

6
ใช่ symlinks นอก repo นั้นใช้ได้ ฉันใช้มันเพื่อชี้ไปยังไดเร็กทอรีข้อมูลขนาดใหญ่ที่ฉันไม่ต้องการ (หรือต้องการ) เวอร์ชัน โดยทั่วไปฉันใช้ลิงก์ที่เกี่ยวข้อง ดังนั้นในกรณีที่ repo และไดเร็กทอรีข้อมูลต้องนั่งติดกันในไดเร็กทอรีหลักบางรายการ คุณสามารถทำเทคนิคที่น่าทึ่งด้วย symlink เพื่อ ../foo
Adrian Ratnapala

น่าเสียดายที่ที่เก็บ Git สำหรับmetastore (git: //git.hardeman.nu/metastore.git) ไม่สามารถใช้ได้อีกต่อไป
Derek Mahar

1
github.com/danny0838/git-store-metaเป็นทางเลือกให้Git-cache-meta
Derek Mahar

22

ฉันพบว่าการใช้ hooks คุณสามารถจับภาพgit pullเหตุการณ์ได้ (เมื่อมีบางอย่างที่จะดึง ... ) เขียนตัวจัดการเหตุการณ์สคริปต์ไปที่.git/hooks/post-mergeไฟล์

ก่อนอื่นคุณต้อง chmod +xมัน

จากนั้นใส่ไฟล์ lnคำสั่งข้างในเพื่อสร้างฮาร์ดลิงก์ขึ้นมาใหม่ในแต่ละครั้งที่ดึง เรียบร้อยฮะ!

ได้ผลฉันแค่ต้องการสิ่งนั้นสำหรับโครงการของฉันและls -iแสดงให้เห็นว่าไฟล์ถูกเชื่อมโยงโดยอัตโนมัติหลังจากpullนั้น


ตัวอย่างของฉัน.git/hooks/post-merge:

#!/bin/sh
ln -f $GIT_DIR/../apresentacao/apresentacao.pdf $GIT_DIR/../capa/apresentacao.pdf
ln -f $GIT_DIR/../avaliacoesMono/avaliacao_monografias_2011_Nilo.pdf $GIT_DIR/../capa/avaliacoes.pdf
ln -f $GIT_DIR/../posters/poster_Nilo_sci.pdf $GIT_DIR/../capa/poster.pdf
ln -f $GIT_DIR/../monografia/monografia_Nilo.pdf $GIT_DIR/../capa/monografia_Nilo.pdf

สำคัญ: อย่างที่คุณเห็นเส้นทางไปยังไฟล์ใด ๆ ในที่เก็บของคุณควรเริ่มต้นด้วย $GIT_DIRจากนั้นเพิ่มพา ธ สัมพัทธ์บางส่วนลงในไฟล์

ที่สำคัญ: -fจำเป็นเนื่องจากคุณกำลังสร้างไฟล์ปลายทางขึ้นใหม่

แก้ไข

ไคลเอนต์ git สมัยใหม่ดูเหมือนว่าจะรองรับ symlinks และ hardlinks ภายในที่เก็บอย่างเป็นธรรมชาติแม้ว่าจะผลักดันไปยังตำแหน่งระยะไกลแล้วทำการโคลนจากมัน ฉันไม่จำเป็นต้องเชื่อมโยงภายนอก repo คอมไพล์อีกแล้ว ...

$ mkdir tmp
$ cd tmp
$ git --version
git version 2.24.3 (Apple Git-128)
$ git init .
Initialized empty Git repository in /Users/teixeira/tmp/.git/
$ mkdir x
$ cd x
$ echo 123 > original
$ cat original
123
$ cd ..
$ ln -s x/original symlink
$ cat symlink
123
$ ln x/original hardlink
$ cat hardlink
123
$ git add .
$ git commit -m 'Symlink and hardlink commit'
[master (root-commit) 8df3134] Symlink and hardlink commit
 3 files changed, 3 insertions(+)
 create mode 100644 hardlink
 create mode 120000 symlink
 create mode 100644 x/original

การโคลนจากที่เก็บ git ในเครื่อง

$ cd
$ git clone tmp/ teste_tmp
Cloning into 'teste_tmp'...
done.
$ cd teste_tmp/
$ ls
hardlink  symlink  x
$ cat symlink
123
$ cat hardlink
123

การโคลนจากที่เก็บระยะไกล

$ cd ~/tmp
$ git remote add origin https://github.com/myUser/myRepo.git
$ git push origin master
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (5/5), 361 bytes | 361.00 KiB/s, done.
Total 5 (delta 0), reused 0 (delta 0)
To https://github.com/myUser/myRepo.git
 + 964dfce...8df3134 master -> master
$ cd ../
$ git clone https://github.com/myUser/myRepo.git
Cloning into 'myRepo'...
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 5 (delta 0), reused 5 (delta 0), pack-reused 0
Unpacking objects: 100% (5/5), done.
$ cd myRepo/
$ cat symlink
123
$ cat hardlink
123

https://github.com/mokacoding/symlinksยังชี้ให้เห็นถึงสิ่งที่สำคัญ: symlink ต้องได้รับการกำหนดค่อนข้าง


11
ดูเหมือนว่าทุกครั้งที่คุณเพิ่มฮาร์ดลิงก์ไปยัง repo ของคุณคุณจะต้องเพิ่มบรรทัดลงในสคริปต์เบ็ดหลังการผสานด้วยตนเองด้วย คงจะดีไม่น้อยหาก Pre-Commit hook ของคุณสร้างสิ่งนี้โดยอัตโนมัติอย่างสมบูรณ์ - ตรวจจับลิงก์ที่ยาก (และสัญลักษณ์) ในคอมมิตของคุณและเขียนบรรทัดที่เหมาะสมลงในไฟล์หลังการผสานของคุณ Git ไม่จำเป็นต้องเก็บข้อมูลไอโหนดใน repo มันจะเก็บบิตของมันไว้ในตะขอ! แต่จะยุ่งแค่ไหนถ้าไฟล์ที่เชื่อมโยงถูกติดตามใน git repo อื่น ... การแก้ไขไฟล์ในที่เดียวจะแพร่กระจายไปยัง repo อื่นได้อย่างราบรื่นหรือไม่? Perpetual ผสานกับวงผลัก / ดึงแบบวงกลม?
เตา

วิธีการที่ชาญฉลาด แต่โชคร้ายที่ Git ไม่ติดตามฮาร์ดลิงก์แม้กระทั่งอาจแสดงว่าเป็นสำเนาในระบบไฟล์ที่ไม่รองรับฮาร์ดลิงก์
Derek Mahar

1
@hobs ขอโทษที่ใช้เวลา 7 ปีในการตอบกลับ :) คุณพูดถูก หากไฟล์ภายนอกที่เก็บถูกเชื่อมโยงโดย 2 ที่เก็บที่แตกต่างกันฉันคิดว่าการเปลี่ยนลิงก์ใน repo หนึ่งจะไม่สามารถมองเห็นได้ในอีกที่หนึ่ง
Niloct

8

จากปัญหา msysgit นี้

จุดเชื่อมต่อไม่ใช่ลิงก์สัญลักษณ์ ดังนั้นลิงก์สัญลักษณ์จึงไม่รองรับใน msysGit

นอกจากนี้ยังเชื่อมโยงอย่างหนักไม่เคยถูกติดตามโดย Git

ปัญหานี้มุ่งเน้นไปที่ Windows (เนื่องจากเป็นเรื่องเกี่ยวกับ msysgit) และการอภิปรายเกี่ยวกับการสนับสนุนที่เป็นไปได้ของ symlink
แต่ความคิดเห็นเกี่ยวกับฮาร์ดลิงค์เกี่ยวข้องกับ Git โดยทั่วไป


2

Google 'git เก็บฮาร์ดลิงก์' และแสดงให้เห็นว่าคอมไพล์ไม่ทราบวิธีรักษาโครงสร้างฮาร์ดลิงก์ AFAIK ไว้โดยอาจเป็นการออกแบบ

โครงการเว็บของฉันใช้ฮาร์ดลิงก์ดังนี้:

www/products/index.php
www/products/dell_latitude_id577/index.php #(hard linked to above)
www/products/dell_inspiron_id323/index.php #(hard linked again to above)

me@server:www/products$ ls -l index.php
-rwxr-xr-x 3 me me 1958 Aug 22 22:10 index.php*

หากฉันต้องการเปลี่ยนแปลง index.php ฉันจะเปลี่ยนในที่เดียวและฮาร์ดลิงก์ (หน้ารายละเอียดผลิตภัณฑ์) ชี้ไปที่การเปลี่ยนแปลง - ยกเว้น git จะไม่รักษาความสัมพันธ์นี้ระหว่างการโคลนและดึงข้อมูลบนคอมพิวเตอร์เครื่องอื่น

me@server:www$ git pull

บนเครื่องอื่นจะสร้าง index.php ใหม่สำหรับแต่ละฮาร์ดลิงก์


7
คุณควรใช้การกำหนดเส้นทางบางประเภทในเว็บแอปของคุณ การเชื่อมโยงแบบยากเป็นเรื่องแปลกประหลาด
Nowaker

5
ใช่อย่างน้อยก็ใช้ symlinks :)
Andres Riofrio

2
นี่คือสิ่งที่ฉันต้องการจริงๆฉันไม่ต้องการให้คอมไพล์เก็บฮาร์ดลิงก์ ฉันมีไดเร็กทอรี Jenkins ที่มีไดเร็กทอรีพื้นที่ทำงานมากมายและเนื่องจากไปป์ไลน์หลายสาขาจึงมีการทำซ้ำจำนวนมาก ดังนั้นฉันจึงมีงานประจำทุกคืนที่ทำงานhardlink --ignore-timeอยู่/var/lib/jenkinsเพื่อเรียกคืนพื้นที่ดิสก์บางส่วน ในระหว่างวันไฟล์บางไฟล์ไม่ได้รับการเชื่อมโยงอีกครั้งหลังจากนั้นgit pullหรือmvn compileไม่เป็นไรฉันคาดว่าจะเกิดขึ้น หากคอมไพล์เพื่อรักษาฮาร์ดลิงก์กลยุทธ์การรีไซเคิลพื้นที่ดิสก์ของฉันจะไม่ทำงาน
Amedee Van Gasse
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.