Làm cách nào tôi có thể khiến Git theo liên kết tượng trưng?


217

Là tốt nhất của tôi sẽ là một kịch bản shell thay thế các liên kết tượng trưng bằng các bản sao, hoặc có một cách khác để nói với Git để theo các liên kết tượng trưng?

Tái bút: Tôi biết nó không an toàn lắm, nhưng tôi chỉ muốn làm điều đó trong một vài trường hợp cụ thể.


5
Có bất lợi cho việc sử dụng các liên kết cứng cho một cái gì đó như thế này?
Ehtesh Choudhury

12
Với Windows 7, "mklink / d" (liên kết tượng trưng thư mục) không hoạt động với git, nhưng "mklink / j" (jraction) hoạt động tốt.
yoyo

1
Nếu tệp được tự động tạo bởi một ứng dụng sẽ tạo lại nó theo cách nó xóa tệp và tạo tệp mới, thì có, đây là một vấn đề liên kết cứng đến các tệp sẽ không giải quyết được.
Martin Pecka

1
@EhteshChoudhury bạn không thể tạo liên kết cứng cho các thư mục
Gaurav Kansal

Câu trả lời:


46

LƯU Ý: Lời khuyên này hiện đã lỗi thời theo nhận xét kể từ Git 1.6.1. Git đã từng cư xử theo cách này, và không còn như vậy nữa.


Theo mặc định, Git cố gắng lưu trữ các liên kết tượng trưng thay vì theo dõi chúng (để thu gọn và nói chung đó là những gì mọi người muốn).

Tuy nhiên, tôi vô tình quản lý để có được nó để thêm các tập tin ngoài symlink khi symlink là một thư mục.

I E:

  /foo/
  /foo/baz
  /bar/foo --> /foo
  /bar/foo/baz

bằng cách làm

 git add /bar/foo/baz

Nó xuất hiện để làm việc khi tôi thử nó. Tuy nhiên, hành vi đó là không mong muốn của tôi vào thời điểm đó, vì vậy tôi không thể cung cấp cho bạn thông tin ngoài điều đó.


72
Các cam kết 725b06050a083474e240a2436121e0a80bb9f175 và 806d13b1ccdbdde4bbdfb96902791c4b7ed125f6 thay đổi giới thiệu rằng ngừng bạn thêm các tập tin ngoài danh bạ symlinked, vì vậy điều này sẽ không làm việc trong các phiên bản của git từ 1.6.1
Đánh dấu Longair

1
$ git add src / main / path / ConvertSymlinkToDir fatal: 'src / main / path / ConvertSymlinkToDir' nằm ngoài một liên kết tượng trưng
user1767316 21/07/17

2
@ user1767316 đọc toàn bộ, và các ý kiến. Nó được sử dụng để làm việc, nó không còn làm. Phần mềm thay đổi, nhưng câu trả lời chấp nhận chồng chéo không chấp nhận. Tôi đã làm rõ điều này không hoạt động. Nhìn vào một câu trả lời khác.
Kent Fredric

có @KentFrederic nhưng thông báo lỗi chính xác đã trả về giúp người dùng tìm kiếm giải pháp cho vấn đề của mình. Đã cố hủy bỏ downvote nhưng bị khóa xin lỗi. Một mặt, câu trả lời của bạn là đúng khi đưa ra cảnh báo, mặt khác, bạn nên ưu tiên trả lời ngay bây giờ thay vì trong quá khứ
dùng1767316

143

Tôi đã làm gì để thêm các tệp trong liên kết tượng trưng vào Git (Tôi không sử dụng liên kết tượng trưng nhưng):

sudo mount --bind SOURCEDIRECTORY TARGETDIRECTORY

Thực hiện lệnh này trong thư mục do Git quản lý. TARGETDIRECTORYphải được tạo ra trước khi SOURCEDIRECTORYđược gắn vào nó.

Nó hoạt động tốt trên Linux, nhưng không phải trên OS X! Thủ thuật đó cũng giúp tôi với Subversion. Tôi sử dụng nó để bao gồm các tệp từ tài khoản Dropbox, trong đó một thiết kế web thực hiện công cụ của anh ấy / cô ấy.


8
Sẽ là một cách tiếp cận rất tốt nếu không yêu cầu sudo.
MestreLion

13
Để hoàn tác ràng buộc này, sử dụng umount [mydir]. (+1 cho mẹo tuyệt vời của bạn, @ user252400)
JellicleCat

10
Điều này chỉ hoạt động trong phiên. Cách tốt nhất để làm cho nó "vĩnh cửu" là gì?
Adobe

17
@Adobe: đặt nó vào / etc / fstab, như vậy: / sourcedir / targetdir none bind
Alexander Garden

8
sshfs có thể đạt được loại mánh khóe đó mà không cần sudo, ở đây.
PypeBros

75

Tại sao không tạo symlink theo cách khác? Ý nghĩa thay vì liên kết từ kho Git đến thư mục ứng dụng, chỉ cần liên kết theo cách khác.

Ví dụ: giả sử tôi đang thiết lập một ứng dụng được cài đặt ~/applicationcần tệp cấu hình config.conf:

  • Tôi thêm config.confvào kho Git của tôi, ví dụ, tại ~/repos/application/config.conf.
  • Sau đó, tôi tạo một liên kết tượng trưng ~/applicationbằng cách chạy ln -s ~/repos/application/config.conf.

Cách tiếp cận này có thể không phải lúc nào cũng hiệu quả, nhưng nó đã làm việc tốt cho tôi cho đến nay.


5
Có vẻ là cách duy nhất, và nó không tệ ... tôi nghĩ rằng bạn là một cách tiếp cận khá thanh lịch. git theo dõi nội dung, không phải tập tin. Vì vậy, giữ tất cả nội dung cùng nhau và liên kết từ đó đến nơi khác có ý nghĩa
MestreLion

12
Trong trường hợp của tôi, tôi muốn một liên kết từ một git repo đến một liên kết khác, vì vậy tôi có thể chỉnh sửa các tệp ở một trong hai vị trí và cam kết trở lại từ xa tương ứng của họ. Trên Windows 7, một đường nối ("mklink / j") đã thực hiện thủ thuật này.
yoyo

3
tất nhiên. đôi khi câu trả lời chỉ đơn giản như vậy.
BBW trước Windows

Điều gì nếu bạn muốn git cả nguồn VÀ đích? (vì cả hai thuộc về các mã khác nhau mà bạn muốn có trong các kho khác nhau)
DrGC

1
Không trả lời câu hỏi :Â symlink: \
Jerry Green

49

Sử dụng liên kết cứng thay thế. Điều này khác với một liên kết mềm (tượng trưng). Tất cả các chương trình, bao gồm gitsẽ coi tệp là một tệp thông thường. Lưu ý rằng các nội dung có thể được sửa đổi bằng cách thay đổi một trong hai nguồn hoặc đích.

Trên macOS (trước 10.13 High Sierra)

Nếu bạn đã cài đặt git và Xcode, hãy cài đặt hardlink . Đây là một công cụ hiển vi để tạo liên kết cứng .

Để tạo liên kết cứng, chỉ cần:

hln source destination

cập nhật macOS High Sierra

Apple File System có hỗ trợ thư mục liên kết cứng không?

Thư mục liên kết cứng không được Apple File System hỗ trợ. Tất cả các liên kết cứng thư mục được chuyển đổi thành liên kết tượng trưng hoặc bí danh khi bạn chuyển đổi từ định dạng âm lượng HFS + sang APFS trên macOS.

Từ Câu hỏi thường gặp về APFS trên developer.apple.com

Theo dõi https://github.com/selkhateeb/hardlink/issues/31 để biết các lựa chọn thay thế trong tương lai.

Trên Linux và các hương vị Unix khác

Các lnlệnh có thể tạo liên kết cứng:

ln source destination

Trên Windows (Vista, 7, 8, Hoài)

Ai đó đề nghị sử dụng mklink để tạo một điểm nối trên Windows, nhưng tôi chưa thử:

mklink /j "source" "destination"

7
Chỉ cần một lưu ý: về cơ bản đây là những gì tôi đang tìm kiếm, nhưng sau đó tôi đã học được rằng trên Linux, một liên kết cứng không may không thể vượt qua ranh giới hệ thống tập tin (đó là trường hợp sử dụng của tôi).
sdaau

26
Bạn không thể liên kết cứng đến thư mục, bạn có thể?
Nanne

1
ln source destinationcũng hoạt động trong OS X. Đã thử nghiệm trên El Capitan.
Mahdi Dibaiee

7
@Nanne không, nhưng bạn có thể làm : cp -al source destination. `-l 'có nghĩa là các tệp liên kết cứng thay vì sao chép.
Paolo

6
Thật không may, bạn không thể liên kết các thư mục cứng, hoặc qua các ranh giới hệ thống tệp. Điều này làm cho giải pháp này gấp đôi không khả thi đối với tôi.
Konrad Rudolph

25

Đây là một hook pre-commit thay thế các đốm symlink trong chỉ mục, với nội dung của các symlink đó.

Đặt cái này vào .git/hooks/pre-commitvà làm cho nó có thể thực thi được:

#!/bin/sh
# (replace "find ." with "find ./<path>" below, to work with only specific paths)

# (these lines are really all one line, on multiple lines for clarity)
# ...find symlinks which do not dereference to directories...
find . -type l -exec test '!' -d {} ';' -print -exec sh -c \
# ...remove the symlink blob, and add the content diff, to the index/cache
    'git rm --cached "$1"; diff -au /dev/null "$1" | git apply --cached -p1 -' \
# ...and call out to "sh".
    "process_links_to_nondir" {} ';'

# the end

Ghi chú

Chúng tôi sử dụng chức năng tuân thủ POSIX càng nhiều càng tốt; tuy nhiên, diff -akhông tuân thủ POSIX, có thể trong số những thứ khác.

Có thể có một số lỗi / lỗi trong mã này, mặc dù nó đã được thử nghiệm phần nào.


4
Thật tuyệt khi thấy một nỗ lực để thực sự trả lời câu hỏi cho các tệp và không phải thư mục. Tuy nhiên, lưu ý rằng ở trên sẽ vẫn hiển thị typechangetrong git statuscho các tập tin mà thực sự là symlink dù git bây giờ mọi thứ họ không.
David Fraser

1
Cảm ơn vì điều đó; chỉ muốn biết, là process_links_to_nondirgì?
sdaau

@sdaau Đó là tên / argv[0]được sử dụng làm tên lệnh cho shquá trình. (Mất một chút để tôi hiểu điều đó, vì tôi không nhớ đó là gì ☺😃)
Abbafei

3
@Abbafei Bạn có thể sửa đổi tập lệnh để làm cho nó hoạt động trên Ubuntu (14.04) không? Nó đang hiển thị find: missing argument to -exec'. Có thể là một bước thực hiện lệnh từng bước thay vì đường ống & kết hợp mọi thứ thành một dòng duy nhất.
Khurshid Alam

1
@KhurshidAlam Đối với tôi, nó hoạt động để loại bỏ các dòng nhận xét ở giữa các dòng lệnh. Tuy nhiên, hook không hoạt động như mong đợi (tôi nhận được typechangenhư @DavidFraser, nhưng tệp được liên kết dường như không được dàn dựng nữa)
Scz 15/03/2017

14

Bật MacOS(Tôi có Mojave / 10.14, gitphiên bản 2.7.1), sử dụng bindfs.

brew install bindfs

cd /path/to/git_controlled_dir

mkdir local_copy_dir

bindfs </full/path/to/source_dir> </full/path/to/local_copy_dir>

Nó đã được gợi ý bởi các bình luận khác, nhưng không được cung cấp rõ ràng trong các câu trả lời khác. Hy vọng điều này sẽ giúp ai đó tiết kiệm thời gian.


Có vẻ tuyệt vời cho các đội chạy trên mac os, tôi nghĩ các liên kết cứng được nêu dưới đây sẽ hoạt động cho windows và linux.
Devin G Rhode

Điều này rất hữu ích và tôi nghĩ giải pháp tốt nhất cho khả năng hữu ích nhưng còn thiếu trong MacOS. Tuy nhiên, xin lưu ý rằng tôi đã nhận được Failed to resolve... No such file or directorylỗi trừ khi tôi sử dụng tên đường dẫn đầy đủ với bindfslệnh.
nam châm điện

Cảm ơn @elect Magnetgot. Đã thêm làm rõ rằng các đường dẫn đầy đủ cần thiết
ijoseph

1
Hoạt động tuyệt vời trên macos Catalina!
Jerry Green

13

Tôi đã sử dụng để thêm các tập tin ngoài symlink trong một thời gian khá lâu. Điều này được sử dụng để làm việc tốt, mà không thực hiện bất kỳ sắp xếp đặc biệt. Vì tôi đã cập nhật lên Git 1.6.1, nên nó không hoạt động nữa.

Bạn có thể chuyển sang Git 1.6.0 để thực hiện công việc này. Tôi hy vọng rằng một phiên bản Git trong tương lai sẽ có một lá cờ để git-addcho phép nó đi theo liên kết tượng trưng một lần nữa.


12

Tôi cảm thấy mệt mỏi với mọi giải pháp ở đây hoặc là lỗi thời hoặc yêu cầu root, vì vậy tôi đã thực hiện một giải pháp dựa trên LD_PRELOAD (chỉ dành cho Linux).

Nó móc vào nội bộ của Git, ghi đè lên 'đây có phải là một liên kết tượng trưng không?' chức năng, cho phép các liên kết tượng trưng được coi là nội dung của chúng. Theo mặc định, tất cả các liên kết đến bên ngoài repo được nội tuyến; xem liên kết để biết chi tiết.


Giải pháp rất sáng tạo sử dụng LD_PRELOADđể ghi đè các chức năng thư viện!
iBug

Vâng, nhưng nó nên được xây dựng ở đây. Bạn có thể làm điều đó?
Peter Mortensen

Không chắc chắn bao nhiêu công phu sẽ giúp; trừ khi tôi sao chép toàn bộ mã nguồn, câu trả lời này sẽ luôn dựa vào liên kết đó, nơi cũng có thể tìm thấy một readme. Nhưng vâng, tôi đoán tôi có thể tái tạo các phần quan trọng của readme.
Alcaro

Điều này không biên dịch trên OS X (Mojave 10.14.2). Nhận bốn lỗi phàn nàn về 'strchrnul' (ý bạn là 'strchr'?) Và một lỗi về '__xstat64' (ý bạn là '__lxstat64'?). Cuối cùng, tôi nhận được một lỗi "truy cập thành viên vào loại 'dirent64'" không đầy đủ. Xảy ra bất kể tôi sử dụng "make", "make OPT = 1" hay "sh install.sh".
Erik Veland

@ErikVeland Tôi đã thử một chút, nhưng có vẻ như OSX không hỗ trợ LD_PRELOAD, cũng không có gì tương tự. Nhiều tài liệu khác nhau đề xuất nhiều thứ khác nhau, nhưng chúng đều đã vài năm tuổi và Apple thích những thứ không được chấp nhận; Tôi không thể làm cho bất cứ ai trong số họ làm việc. Lấy làm tiếc.
Alcaro

6

Với Git 2.3.2+ (Q1 2015), có một trường hợp khác mà Git sẽ không theo symlink nữa: xem commit e0d201b của Junio ​​C Hamano ( gitster) (người duy trì Git chính)

apply: không chạm vào tệp ngoài liên kết tượng trưng

Bởi vì Git theo dõi liên kết tượng trưng là các liên kết tượng trưng, một con đường mà có một liên kết tượng trưng trong phần đầu của nó (ví dụ path/to/dir/file, nơi path/to/dirlà một liên kết tượng trưng đến một nơi khác, có thể là bên trong hay bên ngoài cây làm việc) không bao giờ có thể xuất hiện trong một bản vá mà hợp lệ áp dụng , trừ khi bản vá tương tự trước tiên loại bỏ liên kết tượng trưng để cho phép một thư mục được tạo ở đó.

Phát hiện và từ chối một bản vá như vậy.

Tương tự, khi một đầu vào tạo ra một liên kết tượng trưng path/to/dirvà sau đó tạo một tệp path/to/dir/file, chúng ta cần gắn cờ nó là một lỗi mà không thực sự tạo path/to/dirliên kết tượng trưng trong hệ thống tệp.

Thay vào đó, đối với bất kỳ bản vá nào trong đầu vào để lại một đường dẫn (nghĩa là không xóa) trong kết quả, chúng tôi kiểm tra tất cả các đường dẫn đối với cây kết quả mà bản vá sẽ tạo bằng cách kiểm tra tất cả các bản vá trong đầu vào và sau đó là mục tiêu của bản vá ứng dụng (chỉ mục hoặc cây làm việc).

Bằng cách này, chúng tôi:

  • bắt một trò nghịch ngợm hoặc một sai lầm để thêm một liên kết tượng trưng path/to/dirvà một tập tin path/to/dir/filecùng một lúc,
  • trong khi cho phép một bản vá hợp lệ loại bỏ một ký hiệu link path/to/dirvà sau đó thêm một tệp path/to/dir/file.

Điều đó có nghĩa là, trong trường hợp đó, thông báo lỗi sẽ không phải là một thông báo chung chung "%s: patch does not apply", nhưng là một thông báo cụ thể hơn:

affected file '%s' is beyond a symbolic link

4

Hmmm, mount --binddường như không hoạt động trên Darwin.

Có ai có một mẹo mà không?

[đã chỉnh sửa]

OK, tôi đã tìm thấy câu trả lời trên Mac OS X là tạo một liên kết cứng. Ngoại trừ việc API đó không được hiển thị thông qua ln, vì vậy bạn phải sử dụng chương trình nhỏ của riêng mình để thực hiện việc này. Đây là một liên kết đến chương trình đó:

Tạo thư mục liên kết cứng trong Mac OS X

Thưởng thức!


1
Nếu thư mục đích của liên kết cứng này là thư mục con của repo git khác, đây sẽ là một sự hỗn loạn. Thực hiện các thao tác git trong liên kết cứng sẽ áp dụng cho repo git khác này. Chỉ cần kiểm tra lại những gì bạn đang làm.
yegle

4
Bạn có thể thực hiện việc này thông qua code.google.com/p/bindfs có thể được cài đặt bằng cổng.
Kit Sunde

0

Tôi đang sử dụng Git 1.5.4.3 và nó đi theo liên kết tượng trưng đã qua nếu nó có dấu gạch chéo. Ví dụ

# Adds the symlink itself
$ git add symlink

# Follows symlink and adds the denoted directory's contents
$ git add symlink/

5
ít nhất là trên OSX, kết quả này làfatal: 'src/' is beyond a symbolic link
Dan Rosenstark

2
Theo giải thích của @Mark Longair, điều này chỉ hoạt động cho đến khi git 1.6.1
MestreLion

đó là vấn đề của tôi, cảm ơn!
Mike Q

0

Chuyển đổi từ symlink có thể hữu ích. Liên kết trong thư mục Git thay vì liên kết tượng trưng bằng tập lệnh .


quan tâm để thêm chi tiết cho câu trả lời của bạn?
Devin G Rhode
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.