Git dan tautan keras

98

Mengingat Git tidak mengenali tautan simbolik yang mengarah ke luar repositori, apakah ada masalah dalam menggunakan tautan keras?

Bisakah Git menghancurkannya? Bisakah Anda menunjukkan informasi rinci kepada saya?

Alfredo Palhares
sumber
2
Apa yang Anda coba lakukan dan mengapa? Tautan keras tidak berbeda dengan file biasa. Jika Anda pernah menarik versi baru dari repositori lain, itu akan menimpa versi yang Anda miliki - apa gunanya menautkan ke sesuatu di luar repo?
Carl Norum
2
Git akan mengenali symlink yang mengarah ke jalur di luar repositori.
mipadi
Tidak mipadi, satu-satunya cara adalah melambaikan file dalam repo dan tautan simbolik di lokasi "sebenarnya" mereka
Alfredo Palhares

Jawaban:

89

Objek 'pohon', merepresentasikan direktori di Git, menyimpan nama file dan (subset dari) izin. Itu tidak menyimpan nomor inode (atau jenis id file lainnya). Oleh karena itu, tautan keras tidak dapat direpresentasikan di git , setidaknya tidak tanpa alat pihak ketiga seperti metastore atau git-cache-meta (dan saya tidak yakin apakah itu mungkin bahkan dengan alat tersebut).

Git mencoba untuk tidak menyentuh file yang tidak perlu diperbarui, tetapi Anda harus memperhitungkan bahwa git tidak mencoba untuk mempertahankan hardlink, sehingga dapat dipecah oleh git.


Tentang tautan simbolik yang menunjuk ke luar repositori : git tidak memiliki masalah dengan mereka dan harus menyimpan konten tautan simbolik ... tetapi utilitas tautan tersebut meragukan bagi saya, karena apakah tautan simbolis itu akan rusak atau tidak tergantung pada tata letak sistem file di luar repositori git , dan tidak di bawah kendali git.

Jakub Narębski
sumber
4
Symlinks ke jalur di luar repo bisa berguna. Saya telah menggunakannya di aplikasi web untuk menunjuk ke database atau file media yang tidak dilacak oleh repo. Dengan begitu, file konfigurasi aplikasi web dapat mengarah ke jalur statis, tetapi lokasi sebenarnya dari jalur tersebut dapat bervariasi antara pengembangan lokal dan lingkungan server.
mipadi
@mipadi: BTW. Gitweb modern memiliki kasus khusus untuk menampilkan symlink yang mengarah setelah normalisasi di luar repositori.
Jakub Narębski
6
Ya, symlink di luar repo baik-baik saja. Saya menggunakannya untuk menunjuk ke direktori data besar yang tidak saya perlukan (atau inginkan) berversi. Umumnya saya menggunakan tautan relatif. Jadi dalam beberapa kasus, repo dan direktori data harus diletakkan bersebelahan di beberapa direktori induk. Anda dapat melakukan trik luar biasa dengan symlink ke ../foo.
Adrian Ratnapala
Sayangnya, repositori Git untuk metastore (git: //git.hardeman.nu/metastore.git) tidak lagi tersedia.
Derek Mahar
1
github.com/danny0838/git-store-meta adalah alternatif dari git-cache-meta .
Derek Mahar
22

Saya menemukan bahwa, dengan menggunakan hooks, Anda dapat menangkap git pullevent (bila ada sesuatu yang menarik ...) menulis event handler skrip ke .git/hooks/post-mergefile.

Pertama, Anda harus melakukannya chmod +x.

Kemudian, masukkan lnperintah di dalamnya untuk membuat ulang tautan keras di setiap tarikan. Rapi ya!

Ini berfungsi, saya hanya membutuhkannya untuk proyek saya dan ls -imenunjukkan bahwa file secara otomatis ditautkan setelahnya pull.


Contoh saya tentang .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

PENTING: Seperti yang Anda lihat, jalur ke file mana pun di repositori Anda harus dimulai dengan $GIT_DIR, lalu tambahkan jalur relatif parsial ke file tersebut.

Juga penting: -fdiperlukan, karena Anda membuat ulang file tujuan.

EDIT

Git client modern tampaknya mendukung symlink dan hardlink di dalam repositori secara alami, bahkan ketika mendorong ke lokasi yang jauh dan kemudian melakukan kloning darinya. Saya tidak pernah perlu lagi untuk menautkan di luar git 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

Kloning dari repositori git lokal

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

Kloning dari repositori jarak jauh

$ 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 juga menunjukkan hal yang penting: symlink harus didefinisikan secara relatif.

Niloct
sumber
11
Jadi sepertinya setiap kali Anda menambahkan hardlink ke repo Anda, Anda juga perlu menambahkan baris ke skrip kait pasca-penggabungan secara manual. Akan menyenangkan jika hook pra-komit Anda membuat ini sepenuhnya otomatis - mendeteksi tautan keras (dan simbolis) dalam komit Anda dan menulis baris yang sesuai ke file pasca-penggabungan Anda. Git tidak perlu menyimpan info inode di repo, ia akan menyimpan sebagian kecilnya di hook! Tapi betapa kacau jika file yang ditautkan dilacak di repo git lain ... apakah pengeditan ke file di satu tempat menyebar ke repo lain dengan lancar? Penggabungan abadi dengan lingkaran dorong / tarik melingkar?
kompor
Pendekatan yang cerdas, tetapi sayangnya Git tidak melacak tautan keras, bahkan berpotensi merepresentasikannya sebagai salinan pada sistem file yang tidak mendukung tautan keras.
Derek Mahar
1
@hobs maaf telah mengambil 7 tahun untuk membalas :) Anda benar. Jika file di luar repositori ditautkan oleh 2 repositori berbeda, saya pikir mengubah tautan di satu repo tidak akan terlihat di repo yang lain.
Niloct
8

Dari masalah msysgit ini

Titik persimpangan bukanlah tautan simbolis; oleh karena itu, tautan simbolik tidak didukung di msysGit.

Juga, tautan keras tidak pernah dilacak oleh Git .

Masalahnya berorientasi Windows (karena ini tentang msysgit) dan perdebatan tentang potensi dukungan symlink.
Tetapi komentar tentang hard link menyangkut Git secara umum.

VonC
sumber
2

Google 'git melestarikan tautan keras' dan ini menunjukkan bahwa git tidak tahu bagaimana menjaga AFAIK struktur tautan keras, mungkin dengan desain.

Proyek web saya menggunakan tautan keras sebagai berikut:

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*

Jika saya ingin membuat perubahan pada index.php, saya mengubahnya di satu tempat dan tautan keras (halaman detail produk) menunjukkan perubahan - kecuali git tidak mempertahankan hubungan ini selama kloning dan penarikan di komputer lain.

me@server:www$ git pull

di komputer lain akan membuat index.php baru untuk setiap tautan keras.

xce_git
sumber
7
Anda harus menerapkan semacam perutean di aplikasi web Anda. Hard linking itu aneh.
Nowaker
5
Ya, setidaknya gunakan symlink. :)
Andres Riofrio
2
Ini sebenarnya yang saya inginkan, saya tidak ingin git menyimpan tautan keras. Saya memiliki direktori Jenkins dengan banyak direktori ruang kerja, dan karena jaringan pipa multibranch, ada banyak duplikasi. Jadi saya memiliki pekerjaan malam yang berjalan hardlink --ignore-timepada /var/lib/jenkins, untuk merebut kembali beberapa ruang disk. Pada siang hari beberapa file dibatalkan tautannya lagi setelahnya git pullatau mvn compiletetapi tidak apa-apa, saya perkirakan itu akan terjadi. Jika git ingin mempertahankan tautan keras, maka strategi daur ulang ruang disk saya tidak akan berhasil.
Amedee Van Gasse