Jak Git obsługuje linki symboliczne?

1607

Jeśli mam plik lub katalog, który jest dowiązaniem symbolicznym, i przesyłam go do repozytorium Git, co się z nim stanie?

Zakładam, że pozostawia go jako łącze symboliczne, dopóki plik nie zostanie usunięty, a następnie, jeśli wyciągniesz plik ze starej wersji, po prostu utworzy normalny plik.

Co robi, gdy usuwam plik, do którego się odwołuje? Czy to tylko zatwierdza wiszący link?

Alex
źródło
19
.gitignorewidzi dowiązanie symboliczne jako plik, a nie folder.
0xcaff
6
Cóż, najwyraźniej pytanie ma więcej niż sugeruje ta odpowiedź. Na przykład zastanawiam się, co następuje: jeśli utworzę łącze sym w moim repozytorium do jakiegoś dużego pliku w tym repozytorium, wypchniesz zmiany, a następnie przeciągniesz te zmiany na inny komputer, co się stanie? Czy duży plik będzie przechowywany jako duży plik w obu lokalizacjach, czy też łącze sym zostanie zachowane, tak że na nowym komputerze plik łącza wskazuje oryginalny duży plik?
jvriesem
7
To jest stary wątek, ale ten komentarz może być nadal przydatny. W odpowiedzi na jviesem, miękki link jest w zasadzie plikiem o nazwie innego pliku. Więc kiedy wyciągniesz go na inną maszynę, link zostanie pobrany i będzie miał nazwę dużego pliku w oryginalnym systemie plików. Jeśli na nowym komputerze nazwa jest nieprawidłowa, wówczas link będzie miał niepoprawną nazwę. Duży plik nie zostanie pobrany na nową maszynę.
lasaro,
6
@lasaro, sposobem na uniknięcie zepsutych linków w repozytorium git jest zawsze używanie ścieżek względnych podczas tworzenia dowiązań symbolicznych, używając ../..w razie potrzeby.
Wildcard
8
Zauważ, że w większości wersji systemu Windows potrzebujesz podwyższonych uprawnień, aby utworzyć dowiązanie symboliczne. Jeśli korzystasz z systemu Windows i tworzysz git pullplik zamiast dowiązania symbolicznego, spróbuj uruchomić klienta Git jako administrator.
axmrnv

Odpowiedzi:

1348

Git po prostu przechowuje zawartość łącza (tj. Ścieżkę obiektu systemu plików, do którego się łączy) w „obiekcie blob”, tak jak w przypadku zwykłego pliku. Następnie przechowuje nazwę, tryb i typ (w tym fakt, że jest to dowiązanie symboliczne) w obiekcie drzewa reprezentującym jego zawierający katalog.

Podczas pobierania drzewa zawierającego łącze przywraca on obiekt jako dowiązanie symboliczne niezależnie od tego, czy istnieje docelowy system plików.

Usunięcie pliku, do którego odwołuje się dowiązanie symboliczne, nie wpływa w żaden sposób na dowiązanie symboliczne kontrolowane przez Git. Będziesz miał wiszące odniesienie. Od użytkownika zależy usunięcie lub zmiana linku, aby w razie potrzeby wskazał coś ważnego.

CB Bailey
źródło
328
BTW. Jeśli korzystasz z systemu plików takiego jak FAT, który nie obsługuje dowiązań symbolicznych, a repozytorium ich używa, możesz ustawić core.symlinkszmienną konfiguracyjną na wartość false, a dowiązania symboliczne zostałyby wypisane jako małe pliki zwykłego tekstu zawierające link.
Jakub Narębski
14
@ JakubNarębski Widziałem to wcześniej. W naszym repozytorium był plik tekstowy z jedną linią, ścieżką do używanej biblioteki. Nie mogłem ustalić, jaki był tego cel. Teraz wiem, co się stało.
Matt K
25
Waham się, komentując bardzo wysoko ocenioną odpowiedź, ale myślę, że sformułowanie „tak jak w przypadku zwykłego pliku” może wprowadzać nowych użytkowników w błąd.
Matthew Hannigan
10
(zabrakło czasu edycji) To jest jak normalny plik tylko w tym, że zawartość jest w obiekcie blob. Krytyczna różnica polega na tym, że w przypadku zwykłego pliku obiekt blob jest zawartością pliku, ale w przypadku dowiązania symbolicznego obiekt blob ma nazwę ścieżki do pliku, z którym się łączy. @ JakubNarębski Odnośnie „małych zwykłych plików tekstowych”. Miałbyś nadzieję, że są one małe i zawierają tekst, ale oczywiście kropelka jest kroplą i potencjalnie może być duża i binarna. Zobacz stackoverflow.com/questions/18411200/ ..., kiedy plik jest błędnie wpisany jako dowiązanie symboliczne.
Matthew Hannigan
2
Sprawdź ustawienia globalne dla dowiązań symbolicznych i ustawienia lokalne dla dowiązań symbolicznych. Jeśli ustawienia zostały skopiowane z TortiseGit lub Windows, możesz mieć symlinks = falsez nimi problemy.
phyatt,
250

Możesz dowiedzieć się, co Git robi z plikiem, widząc, co robi po dodaniu go do indeksu. Indeks jest jak zatwierdzenie wstępne. Po zatwierdzeniu indeksu można użyć git checkoutdo przeniesienia wszystkiego, co było w indeksie z powrotem do katalogu roboczego. Co więc robi Git, gdy dodasz dowiązanie symboliczne do indeksu?

Aby się dowiedzieć, najpierw utwórz dowiązanie symboliczne:

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

Git jeszcze nie wie o tym pliku. git ls-filespozwala kontrolować swoje (indeks -sdrukuje statwyjście -Jak):

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

Teraz dodaj zawartość dowiązania symbolicznego do składnicy obiektów Git, dodając go do indeksu. Po dodaniu pliku do indeksu Git przechowuje jego zawartość w magazynie obiektów Git.

$ git add ./symlink

Co więc zostało dodane?

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

Hash jest odniesieniem do spakowanego obiektu, który został utworzony w magazynie obiektów Git. Możesz zbadać ten obiekt, jeśli zajrzysz .git/objects/15/96f9db1b9610f238b78dd168ae33faa2dec15cdo katalogu głównego repozytorium. To jest plik, który Git przechowuje w repozytorium, który możesz później sprawdzić. Jeśli przejrzysz ten plik, zobaczysz, że jest on bardzo mały. Nie przechowuje zawartości połączonego pliku.

(Uwaga 120000to tryb wymieniony w ls-filesdanych wyjściowych. Byłby podobny 100644do zwykłego pliku.)

Ale co Git robi z tym obiektem, gdy wypisujesz go z repozytorium i do swojego systemu plików? To zależy od core.symlinkskonfiguracji. Od man git-config:

core.symlinks

Jeśli false, dowiązania symboliczne są sprawdzane jako małe zwykłe pliki zawierające tekst łącza.

Tak więc, z dowiązaniem symbolicznym w repozytorium, przy kasie otrzymujesz albo plik tekstowy z odniesieniem do pełnej ścieżki systemu plików, albo odpowiednie dowiązanie symboliczne, w zależności od wartości core.symlinkskonfiguracji.

Tak czy inaczej dane, do których odwołuje się dowiązanie symboliczne, nie są przechowywane w repozytorium.

Dmitrij Minkowski
źródło
1
Wspaniała odpowiedź
CervEd
147

Uwaga redaktora: ten post może zawierać nieaktualne informacje. Zobacz komentarze i to pytanie dotyczące zmian w Git od 1.6.1.

Symlinkowane katalogi:

Ważne jest, aby pamiętać, co dzieje się, gdy istnieje katalog będący miękkim łączem. Każde pobranie Git wraz z aktualizacją usuwa link i czyni go normalnym katalogiem. Tego nauczyłem się na własnej skórze. Niektóre spostrzeżenia tu i tutaj.

Przykład

Przed

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

git add/commit/push

It remains the same

Po git pullAND znaleziono kilka aktualizacji

 drwxrwsr-x 2 admin adm 4096 Oct  2 05:54 src/somedir
Shekhar
źródło
4
Warto zauważyć, że te ostrzeżenia dotyczące katalogów dowiązań symbolicznych nie dotyczą wersjonowanych dowiązań symbolicznych. Najważniejszy przypadek, o którym mowa, dotyczył osób symbolizujących niektóre lub wszystkie działające drzewa w innej ścieżce (powiedzmy na innej partycji z większą ilością miejsca na dysku) i oczekujących, że git sprawdzi kod poprzez istniejące łącze symboliczne. Oznacza to, że jeśli masz projekt zawierający wersjonowane dowiązania symboliczne do plików lub katalogów, normalne zachowanie symlink-as-blob zachowa dowiązania symboliczne, poprawi zmiany wersji tych dowiązań symbolicznych i w przeciwnym razie będzie działało zgodnie z oczekiwaniami.
John Whitley,
Powyższe zachowanie przetestowane z git 1.6.5.6; ale mocno podejrzewam, że zachowanie wersjonowane jest poprawne w git od dłuższego czasu.
John Whitley,
22
Czy takie zachowanie występuje we wszystkich wersjach git, czy też zostało to naprawione?
jbotnik
24
Wygląda na to, że to zachowanie zostało już naprawione, patrz: stackoverflow.com/a/1943656/1334781
Ron Wertlen
2
Shekar: Czy umieścisz edycję swojej odpowiedzi, aby odzwierciedlić zmiany w git w ostatnich latach?
einpoklum