Làm thế nào để Git xử lý các liên kết tượng trưng?


1607

Nếu tôi có một tập tin hoặc thư mục là một liên kết tượng trưng và tôi cam kết nó với một kho lưu trữ Git, điều gì xảy ra với nó?

Tôi sẽ giả sử rằng nó để nó như một liên kết tượng trưng cho đến khi tệp bị xóa và sau đó nếu bạn kéo tệp trở lại từ một phiên bản cũ, nó chỉ tạo một tệp bình thường.

Nó làm gì khi tôi xóa tập tin nó tham chiếu? Nó chỉ cam kết liên kết lơ lửng?


19
.gitignorethấy symlink như một tập tin chứ không phải một thư mục.
0xcaff

6
Chà, rõ ràng là có nhiều câu hỏi hơn câu trả lời đó ngụ ý. Chẳng hạn, tôi đang tự hỏi như sau: nếu tôi tạo một liên kết sym trong kho lưu trữ của mình đến một số tệp lớn trong kho lưu trữ đó, đẩy các thay đổi và sau đó kéo các thay đổi đó sang một máy khác, điều gì sẽ xảy ra? Tệp lớn sẽ được lưu trữ dưới dạng tệp lớn ở cả hai vị trí hay liên kết sym sẽ được giữ nguyên, như vậy trên máy mới, tệp liên kết sẽ trỏ đến tệp lớn ban đầu?
jvriesem

7
Đây là một chủ đề cũ nhưng nhận xét này có thể vẫn hữu ích. Để đáp ứng với jviesem, một liên kết mềm về cơ bản là một tệp có tên của một tệp khác. Vì vậy, một khi bạn kéo nó đến một máy khác, liên kết sẽ được tải xuống và nó sẽ có tên của tệp lớn trên hệ thống tệp gốc. Nếu trên máy mới, tên không hợp lệ, thì liên kết sẽ có tên không hợp lệ. Các tập tin lớn sẽ không được tải xuống máy mới.
lasaro

6
@lasaro, cách để tránh các liên kết bị hỏng trong repo git là luôn luôn sử dụng các đường dẫn tương đối khi tạo các liên kết tượng trưng, ​​sử dụng ../..khi cần thiết.
tự đại diện

8
Lưu ý rằng trong hầu hết các phiên bản Windows, bạn cần có quyền nâng cao để tạo liên kết tượng trưng. Nếu bạn đang ở trên Windows và git pulltạo một tệp thay vì liên kết tượng trưng, ​​hãy thử chạy ứng dụng khách Git của bạn với tư cách quản trị viên.
axmrnv

Câu trả lời:


1348

Git chỉ lưu trữ nội dung của liên kết (tức là đường dẫn của đối tượng hệ thống tệp mà nó liên kết đến) trong một 'blob' giống như đối với một tệp bình thường. Sau đó, nó lưu trữ tên, chế độ và loại (bao gồm cả thực tế là một liên kết tượng trưng) trong đối tượng cây đại diện cho thư mục chứa của nó.

Khi bạn kiểm tra một cây có chứa liên kết, nó sẽ khôi phục đối tượng dưới dạng symlink bất kể đối tượng hệ thống tệp đích có tồn tại hay không.

Nếu bạn xóa tệp mà liên kết tượng trưng tham chiếu thì nó không ảnh hưởng đến liên kết tượng trưng do Git kiểm soát theo bất kỳ cách nào. Bạn sẽ có một tài liệu tham khảo lơ lửng. Người dùng có quyền xóa hoặc thay đổi liên kết để trỏ đến một cái gì đó hợp lệ nếu cần.


328
BTW. Nếu bạn đang sử dụng hệ thống tệp như FAT không hỗ trợ các liên kết tượng trưng và kho lưu trữ của bạn sử dụng chúng, bạn có thể đặt core.symlinksbiến cấu hình thành false và các liên kết tượng trưng sẽ được kiểm tra dưới dạng tệp văn bản đơn giản có chứa văn bản liên kết.
Jakub Narębski

14
@ JakubNarębski Tôi đã thấy điều này trước đây. Có một tệp văn bản trong repo của chúng tôi với một dòng, một đường dẫn đến thư viện chúng tôi sử dụng. Không thể tìm ra mục đích của nó là gì. Tôi biết bây giờ những gì đã xảy ra.
Matt K

25
Tôi ngần ngại nhận xét về câu trả lời được đánh giá cao nhưng tôi nghĩ rằng cụm từ "giống như nó sẽ làm cho một tập tin bình thường" có thể gây hiểu lầm cho người mới.
Matthew Hannigan

10
(hết thời gian chỉnh sửa) Nó giống như một tệp bình thường chỉ trong đó nội dung nằm trong một blob. Sự khác biệt quan trọng là đối với một tệp bình thường, blob là nội dung tệp nhưng đối với một liên kết tượng trưng thì blob có tên đường dẫn của tệp mà nó liên kết đến. @ JakubNarębski Về "tệp văn bản nhỏ đơn giản" .. Bạn sẽ hy vọng chúng nhỏ và văn bản nhưng tất nhiên một blob là một blob và có khả năng có thể rất lớn và nhị phân. Xem stackoverflow.com/questions/18411200/ Khăn để biết khi một tệp bị nhập nhầm thành một liên kết tượng trưng.
Matthew Hannigan

2
Hãy chắc chắn kiểm tra cài đặt toàn cầu của bạn để tìm liên kết tượng trưng và cài đặt cục bộ cho liên kết tượng trưng. Nếu cài đặt được sao chép từ TortiseGit hoặc windows, thì bạn có thể gặp rắc symlinks = falserối với chúng.
phyatt

250

Bạn có thể tìm hiểu những gì Git làm với một tệp bằng cách xem những gì nó làm khi bạn thêm nó vào chỉ mục. Các chỉ số giống như một cam kết trước. Với chỉ mục đã cam kết, bạn có thể sử dụng git checkoutđể đưa mọi thứ trong chỉ mục trở lại thư mục làm việc. Vậy, Git làm gì khi bạn thêm một liên kết tượng trưng vào chỉ mục?

Để tìm hiểu, đầu tiên, tạo một liên kết tượng trưng:

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

Git chưa biết về tập tin này. git ls-filescho phép bạn kiểm tra chỉ mục của bạn ( đầu ra giống như -sin stat):

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

Bây giờ, thêm nội dung của liên kết tượng trưng vào kho đối tượng Git bằng cách thêm nó vào chỉ mục. Khi bạn thêm một tệp vào chỉ mục, Git lưu trữ nội dung của nó trong kho đối tượng Git.

$ git add ./symlink

Vì vậy, những gì đã được thêm vào?

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

Hàm băm là một tham chiếu đến đối tượng được đóng gói đã được tạo trong kho đối tượng Git. Bạn có thể kiểm tra đối tượng này nếu bạn tìm .git/objects/15/96f9db1b9610f238b78dd168ae33faa2dec15ctrong thư mục gốc của kho lưu trữ. Đây là tệp mà Git lưu trữ trong kho lưu trữ, mà sau này bạn có thể kiểm tra. Nếu bạn kiểm tra tệp này, bạn sẽ thấy nó rất nhỏ. Nó không lưu trữ nội dung của tập tin được liên kết.

(Lưu ý 120000là chế độ được liệt kê trong ls-filesđầu ra. Nó sẽ giống như 100644một tệp thông thường.)

Nhưng Git làm gì với đối tượng này khi bạn kiểm tra nó từ kho lưu trữ và vào hệ thống tập tin của bạn? Nó phụ thuộc vào core.symlinkscấu hình. Từ man git-config:

core.symlinks

Nếu sai, các liên kết tượng trưng được kiểm tra dưới dạng các tệp đơn giản nhỏ có chứa văn bản liên kết.

Vì vậy, với một liên kết tượng trưng trong kho lưu trữ, khi thanh toán, bạn có thể nhận được một tệp văn bản có tham chiếu đến đường dẫn hệ thống tệp đầy đủ hoặc một liên kết tượng trưng thích hợp, tùy thuộc vào giá trị của core.symlinkscấu hình.

Dù bằng cách nào, dữ liệu được tham chiếu bởi symlink không được lưu trữ trong kho lưu trữ.


1
Câu trả lời tuyệt vời
Cổ tử cung

147

Lưu ý "Biên tập viên": Bài đăng này có thể chứa thông tin lỗi thời. Vui lòng xem các bình luận và câu hỏi này liên quan đến những thay đổi trong Git kể từ 1.6.1.

Các thư mục được liên kết:

Điều quan trọng cần lưu ý là những gì xảy ra khi có một thư mục là một liên kết mềm. Bất kỳ thao tác kéo Git nào với bản cập nhật sẽ xóa liên kết và biến nó thành một thư mục bình thường. Đây là những gì tôi học được cách khó khăn. Một số hiểu biết ở đâyở đây.

Thí dụ

Trước

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

git add/commit/push

It remains the same

Sau git pullVÀ một số cập nhật được tìm thấy

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

4
Điều đáng chú ý là những cảnh báo về các thư mục được liên kết không áp dụng cho các liên kết tượng trưng được phiên bản. Trường hợp cạnh chính trong câu hỏi là mọi người liên kết một số hoặc tất cả các cây làm việc vào một đường dẫn khác (giả sử trên một phân vùng khác có nhiều không gian đĩa hơn) và mong muốn git kiểm tra mã thông qua liên kết tượng trưng hiện có. Đó là, nếu bạn có một dự án chứa các liên kết tượng trưng được phiên bản đến các tệp hoặc thư mục, thì hành vi symlink-as-blob thông thường sẽ duy trì các liên kết tượng trưng, ​​thay đổi phiên bản chính xác cho các liên kết tượng trưng đó và hoạt động như mong đợi.
John Whitley

Các hành vi trên được thử nghiệm với git 1.6.5.6; nhưng tôi hoàn toàn nghi ngờ rằng hành vi được phiên bản đã chính xác trong git khá lâu.
John Whitley

22
Là hành vi này hiện diện trên tất cả các phiên bản của git hoặc điều này đã được sửa với?
jbotnik

24
Có vẻ như hành vi này đã được khắc phục ngay bây giờ, xem: stackoverflow.com/a/1943656/1334781
Ron Wertlen

2
Shekar: Bạn sẽ chỉnh sửa câu trả lời của mình để phản ánh những thay đổi trong git trong những năm gần đây chứ?
einpoklum
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.