Wird mein Bestes ein Shell-Skript sein, das Symlinks durch Kopien ersetzt, oder gibt es eine andere Möglichkeit, Git anzuweisen, Symlinks zu folgen?
PS: Ich weiß, dass es nicht sehr sicher ist, aber ich möchte es nur in bestimmten Fällen tun.
Wird mein Bestes ein Shell-Skript sein, das Symlinks durch Kopien ersetzt, oder gibt es eine andere Möglichkeit, Git anzuweisen, Symlinks zu folgen?
PS: Ich weiß, dass es nicht sehr sicher ist, aber ich möchte es nur in bestimmten Fällen tun.
Antworten:
HINWEIS: Dieser Hinweis ist seit Git 1.6.1 gemäß Kommentar veraltet. Git hat sich früher so verhalten und tut es nicht mehr.
Git versucht standardmäßig, Symlinks zu speichern, anstatt ihnen zu folgen (aus Gründen der Kompaktheit und im Allgemeinen ist es das, was die Leute wollen).
Ich habe es jedoch versehentlich geschafft, Dateien über den Symlink hinaus hinzuzufügen, wenn der Symlink ein Verzeichnis ist.
Dh:
/foo/
/foo/baz
/bar/foo --> /foo
/bar/foo/baz
indem du es tust
git add /bar/foo/baz
es schien zu funktionieren, als ich es versuchte. Dieses Verhalten war jedoch zu diesem Zeitpunkt von mir unerwünscht, sodass ich Ihnen darüber hinaus keine Informationen geben kann.
Was ich hinzugefügt habe, um die Dateien innerhalb eines Symlinks in Git zu bekommen (ich habe aber keinen Symlink verwendet):
sudo mount --bind SOURCEDIRECTORY TARGETDIRECTORY
Führen Sie diesen Befehl im von Git verwalteten Verzeichnis aus. TARGETDIRECTORY
muss erstellt werden, bevor das SOURCEDIRECTORY
darin montiert wird.
Es funktioniert gut unter Linux, aber nicht unter OS X! Dieser Trick hat mir auch bei Subversion geholfen. Ich verwende es, um Dateien aus einem Dropbox-Konto einzuschließen, in dem ein Webdesigner seine Aufgaben erledigt.
umount [mydir]
. (+1 für Ihren tollen Tipp, @ user252400)
Warum nicht umgekehrt Symlinks erstellen? Das heißt, anstatt vom Git-Repository mit dem Anwendungsverzeichnis zu verknüpfen, verknüpfen Sie einfach umgekehrt.
Angenommen, ich richte eine installierte Anwendung ein, für ~/application
die eine Konfigurationsdatei erforderlich ist config.conf
:
config.conf
meinem Git-Repository beispielsweise bei hinzu ~/repos/application/config.conf
.~/application
indem ich laufe ln -s ~/repos/application/config.conf
.Dieser Ansatz funktioniert möglicherweise nicht immer, hat aber bisher für mich gut funktioniert.
Verwenden Sie stattdessen Hardlinks. Dies unterscheidet sich von einer weichen (symbolischen) Verbindung. Alle Programme, einschließlich git
, behandeln die Datei als reguläre Datei. Beachten Sie, dass der Inhalt geändert werden kann, indem Sie entweder die Quelle oder das Ziel ändern .
Wenn Sie Git und Xcode bereits installiert haben, installieren Sie den Hardlink . Es ist ein mikroskopisches Werkzeug, um harte Links zu erstellen .
Um die feste Verbindung herzustellen, einfach:
hln source destination
Unterstützt Apple File System Verzeichnis-Hardlinks?
Verzeichnis-Hardlinks werden vom Apple File System nicht unterstützt. Alle Verzeichnis-Hardlinks werden in symbolische Links oder Aliase konvertiert, wenn Sie unter macOS von HFS + in APFS-Volume-Formate konvertieren.
Aus den APFS-FAQ auf developer.apple.com
Folgen Sie https://github.com/selkhateeb/hardlink/issues/31 für zukünftige Alternativen.
Der ln
Befehl kann feste Links herstellen:
ln source destination
Jemand hat vorgeschlagen, mit mklink eine Junction unter Windows zu erstellen, aber ich habe es nicht versucht:
mklink /j "source" "destination"
ln source destination
funktioniert auch unter OS X. Getestet auf El Capitan.
cp -al source destination
. `-l 'bedeutet Hardlink-Dateien anstatt zu kopieren.
Dies ist ein Pre-Commit-Hook, der die Symlink-Blobs im Index durch den Inhalt dieser Symlinks ersetzt.
Geben Sie dies ein .git/hooks/pre-commit
und machen Sie es ausführbar:
#!/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
Wir verwenden so oft wie möglich POSIX-kompatible Funktionen. ist jedoch diff -a
möglicherweise unter anderem nicht POSIX-konform.
Es kann einige Fehler in diesem Code geben, obwohl er etwas getestet wurde.
typechange
in git status
für die Dateien , die tatsächlich Symlinks sind allerdings git jetzt Dinge , die sie nicht sind.
process_links_to_nondir
?
argv[0]
der als Befehlsname für den sh
Prozess verwendet wird. (Ich brauchte ein bisschen, um das herauszufinden, da ich mich auch nicht daran erinnerte, was es war ☺😃)
find: missing argument to -exec'
. Möglicherweise ist eine schrittweise Befehlsausführung erforderlich, anstatt alles in einer einzigen Zeile zu kombinieren.
typechange
wie @DavidFraser, aber die verknüpfte Datei scheint nicht mehr inszeniert zu sein)
Ein MacOS
(ich habe Mojave / 10.14, git
Version 2.7.1) verwenden 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>
Es wurde durch andere Kommentare angedeutet, aber in anderen Antworten nicht eindeutig angegeben. Hoffentlich spart dies jemandem etwas Zeit.
Failed to resolve
... No such file or directory
Fehler erhalten habe, es sei denn, ich habe mit dem Befehl vollständige Pfadnamen verwendetbindfs
.
Ich habe schon seit einiger Zeit Dateien jenseits von Symlinks hinzugefügt. Dies funktionierte früher einwandfrei, ohne besondere Vorkehrungen zu treffen. Seit ich auf Git 1.6.1 aktualisiert habe, funktioniert dies nicht mehr.
Möglicherweise können Sie zu Git 1.6.0 wechseln, damit dies funktioniert. Ich hoffe, dass eine zukünftige Version von Git eine Flagge hat, git-add
damit es wieder Symlinks folgen kann.
Ich habe es satt, dass jede Lösung hier entweder veraltet ist oder root benötigt, also habe ich eine LD_PRELOAD-basierte Lösung erstellt (nur Linux).
Es fügt sich in Gits Interna ein und überschreibt das "Ist das ein Symlink?" Funktion, mit der Symlinks als Inhalt behandelt werden können. Standardmäßig sind alle Links außerhalb des Repos inline. Siehe den Link für Details.
LD_PRELOAD
zum Überschreiben von Bibliotheksfunktionen!
Mit Git 2.3.2+ (Q1 2015), gibt es einen anderen Fall , in dem Git wird nicht Symlink folgen mehr: siehe begehen e0d201b von Junio C Hamano ( gitster
) (Haupt - Git - Maintainer)
apply
: Berühren Sie keine Datei über einen symbolischen Link hinausDa Git symbolische Links als symbolische Links verfolgt, kann ein Pfad, dessen Hauptteil einen symbolischen Link enthält (z. B.
path/to/dir/file
wopath/to/dir
sich ein symbolischer Link zu einem anderen Ort befindet, sei es innerhalb oder außerhalb des Arbeitsbaums), niemals in einem gültigen Patch erscheinen , es sei denn, derselbe Patch entfernt zuerst den symbolischen Link, damit dort ein Verzeichnis erstellt werden kann.Erkennen Sie einen solchen Patch und lehnen Sie ihn ab.
Wenn eine Eingabe eine symbolische Verknüpfung erstellt
path/to/dir
und dann eine Datei erstelltpath/to/dir/file
, müssen wir sie als Fehler kennzeichnen, ohne tatsächlich einepath/to/dir
symbolische Verknüpfung im Dateisystem zu erstellen .Stattdessen überprüfen wir für jeden Patch in der Eingabe, der einen Pfad (dh ein Nichtlöschen) im Ergebnis hinterlässt, alle führenden Pfade anhand des resultierenden Baums, den der Patch erstellen würde, indem wir alle Patches in der Eingabe und dann das Ziel des Patches untersuchen Anwendung (entweder der Index oder der Arbeitsbaum).
Auf diese Weise können wir:
- einen Unfug oder einen Fehler abfangen, um gleichzeitig einen symbolischen Link
path/to/dir
und eine Datei hinzuzufügenpath/to/dir/file
,- Dabei wird ein gültiger Patch zugelassen, der ein Symbol entfernt
link path/to/dir
und dann eine Datei hinzufügtpath/to/dir/file
.
Das heißt, in diesem Fall ist die Fehlermeldung keine generische "%s: patch does not apply"
, sondern eine spezifischere:
affected file '%s' is beyond a symbolic link
Hmmm, mount --bind
scheint bei Darwin nicht zu funktionieren.
Hat jemand einen Trick, der das tut?
[bearbeitet]
OK, ich fand die Antwort unter Mac OS X, einen Hardlink zu erstellen. Abgesehen davon, dass diese API nicht über verfügbar gemacht wird ln
, müssen Sie dazu Ihr eigenes kleines Programm verwenden. Hier ist ein Link zu diesem Programm:
Erstellen von Verzeichnis-Hardlinks in Mac OS X.
Genießen!
Ich verwende Git 1.5.4.3 und es folgt dem übergebenen Symlink, wenn es einen abschließenden Schrägstrich hat. Z.B
# Adds the symlink itself
$ git add symlink
# Follows symlink and adds the denoted directory's contents
$ git add symlink/
fatal: 'src/' is beyond a symbolic link
Die Konvertierung von Symlinks kann hilfreich sein. Link in einem Git-Ordner anstelle eines Symlinks durch ein Skript .