Sparse Checkout in Git 1.7.0?

70

Ist es mit der neuen Funktion zum Auschecken mit geringer Dichte in Git 1.7.0 möglich, nur den Inhalt eines Unterverzeichnisses abzurufen, wie Sie es in SVN können? Ich habe dieses Beispiel gefunden , aber es behält die vollständige Verzeichnisstruktur bei. Stellen Sie sich vor, ich wollte nur den Inhalt des Verzeichnisses 'perl' ohne ein tatsächliches Verzeichnis namens 'perl'.

- BEARBEITEN -

Beispiel:

Mein Git-Repository enthält die folgenden Pfade

repo/.git/
repo/perl/
repo/perl/script1.pl
repo/perl/script2.pl
repo/images/
repo/images/image1.jpg
repo/images/image2.jpg
repo/doc/
repo/doc/readme.txt
repo/doc/help.txt

Was ich möchte, ist, aus dem obigen Repository dieses Layout erstellen zu können:

repo/.git/
repo/script1.pl
repo/script2.pl

Mit der aktuellen Funktion zum Auschecken mit geringer Dichte scheint es jedoch nur möglich zu sein, diese zu erhalten

repo/.git/
repo/perl/script1.pl
repo/perl/script2.pl

Das ist NICHT was ich will.

davr
quelle
4
sie haben es endlich umgesetzt! cool!
Mauricio Scheffer
Warum? Worin besteht das Problem? Und warum möchten Sie eine andere Verzeichnisstruktur im Repository und eine andere lokal haben? Macht auf den ersten Blick wenig Sinn.
Jiri Klouda
2
@Jiri: Ich habe eine Webanwendung mit Actionscript (clientseitig) und PHP (serverseitig) Code. Die Dateien sind eng miteinander verbunden, daher möchte ich sie in einem einzigen Repo / Zweig zusammenfassen. Ich möchte jedoch nicht die Actionscript-Quelldateien auf dem Server, sondern nur die PHP-Dateien.
Davr
2
@davr das ist kein so seltener Umstand, ich wollte genau das. Schade, dass ich es noch nicht bekommen kann.
Preinheimer
@preinheimer, es ist auch etwas, was ich versuche zu bekommen. Es würde das Entwickeln und Testen eines Themas erleichtern, das ich viel einfacher mache.
Apokaliptis

Antworten:

27

Sie müssen noch das gesamte Repository klonen, das alle Dateien enthält. Sie können das --depthFlag verwenden, um nur eine begrenzte Anzahl von Verlaufsdaten abzurufen.

Sobald das Repository geklont ist, beschränkt der Lesebaum-Trick Ihre "Ansicht" des Repositorys auf nur die Dateien oder Verzeichnisse, die sich in der .git/info/sparse-checkoutDatei befinden.

Ich habe ein schnelles Skript geschrieben, um die Spärlichkeit zu bewältigen, da es im Moment etwas unfreundlich ist:

#!/bin/sh
echo > .git/info/sparse-checkout
for i in "$@"
do
    echo "$i" >> .git/info/sparse-checkout
done
git read-tree -m -u HEAD

Wenn Sie dieses Skript git-sparse.shin dem Pfad speichern , der durch Aufrufen gemeldet wurde, git --exec-pathkönnen Sie git sparse foo/ bar/nur die Verzeichnisse foo und bar "auschecken" oder git sparse '*'alles wieder zurückerhalten.

richq
quelle
Danke für die Hilfe, aber das scheint meine Frage nicht zu beantworten. Siehe meine aktualisierte Frage zur Klarstellung.
Davr
3
Ja, spärlich ist nur eine Möglichkeit, den tatsächlichen Baum zu filtern. Es kann keine Dateien verschieben. Sie können also nicht tun, was Sie wollen ...
richq
16

Die kurze Antwort lautet nein. Git sieht alle Dateien als eine Einheit.

Was ich empfehle, ist, dass Sie Ihre Repositorys in logische Blöcke aufteilen. Eine separate für Perl, Bilder und Dokumente. Wenn Sie auch den Uber-Repo-Stil beibehalten müssen, können Sie ein Repo aus Submodulen erstellen .

John K.
quelle
5

Ohne ins Detail zu gehen, warum Sie dies tun möchten, kann Ihr Problem (wahrscheinlich) einfach durch einen Symlink / eine Verknüpfung gelöst werden.

Um die Frage zu beantworten - nein und mit einem sinnvollen Grund. Die gesamte Geschichte des Repos wird auch bei einem "spärlichen Checkout" heruntergeladen. Um zu klären, warum dies notwendig ist - andernfalls wäre das Verfolgen umbenannter Dateien ein Schmerz im Nacken. Stellen Sie sich vor, Sie verschieben die Datei /repo_root/asd/file1.cppnach /repo_root/fgh/file1.cpp- wenn Sie jetzt nur /repo_root/fghDeltas heruntergeladen haben , wissen Sie nichts über file1.cpp. Das bedeutet, dass Sie alle Deltas herunterladen müssen. Aber dann haben Sie ein vollständiges Repository; nicht nur ein Ordnerausschnitt davon, daher ist nur der /rero_root/fghOrdner selbst kein Repo. Dies mag beim Auschecken nicht wichtig klingen, aber wenn Sie sich verpflichten, weiß Git möglicherweise nicht genug, um in Ordnung zu funktionieren.

Problemumgehung : Wenn Sie wirklich möchten, können Sie ein Skript erstellen, das git-checkout auf diese Weise aufruft (für die sh-Shell sollte es nicht schwierig sein, einen Stapel für Windows zu erstellen):

!/bin/sh
curDir=`pwd`
cd $2
git-checkout $1
cp -R $3/* $4
cd $curDir

Hier ist das erste Argument der Zweig zum Auschecken, das zweite - der Ordner, in dem sich das Repo gerade befindet, das dritte - das Unterverzeichnis, das Sie wirklich verwenden möchten, und das vierte - der Speicherort, an den es kopiert werden soll.

Warnung: Meine Shell-Fähigkeiten sind fast nicht vorhanden. Verwenden Sie diese nach dem Testen. Es sollte nicht schwer sein, die Rückseite dieses Skripts neu zu erstellen, das zurückkopiert, damit es für das Repo festgeschrieben werden kann.

Ger4ish
quelle
Die gesamte Geschichte des Repos zu haben ist kein Problem, es ist kein großes Repo, und wir haben viel Speicherplatz. Ich denke, unser spezieller Anwendungsfall ist nicht so häufig, also hätten Git-Entwickler nie daran gedacht, ihn hinzuzufügen. Es ist eines der wenigen Dinge, die SVN für uns besser funktioniert hat (Git macht 99 andere Dinge besser, weshalb wir gewechselt haben, aber immer noch)
Davr
Symlinks auf Fenstern sind ein Albtraum - dies ist nicht nachvollziehbar.
Alex Brown
3

git filter-branch --subdirectory-filterist das, was Sie brauchen, siehe Unterverzeichnis trennen (verschieben) in separates Git-Repository .

Hier ist ein kleines Bash-Skript, um das zu tun.

Dadurch wird zuerst eine Arbeitskopie des ursprünglichen Repos erstellt und anschließend der Zweig mithilfe des Unterverzeichnisfilters gefiltert, um das zu erhalten, was Sie möchten.

#!/bin/bash
#
# git-subdir.sh
#
git clone --no-hardlinks $1 $2

cd $2

git filter-branch --subdirectory-filter $2 --prune-empty --tag-name-filter cat HEAD -- --all

git reset --hard

git remote rm origin

refbak=$(git for-each-ref --format="%(refname)" refs/original/)

if [ -n "$refbak" ];then
    echo -n $refbak | xargs -n 1 git update-ref -d
fi

git reflog expire --expire=now --all

git repack -ad

git gc --aggressive --prune=now

Verwenden Sie für das Beispiel in der Frage, git-subdir.sh repo perlwürde funktionieren.

weynhamz
quelle
0

Es scheint, dass Sie versuchen, den Verzeichnisbaum so umzubenennen, dass Ihre Dateien an einem anderen Ort landen. Es scheint mir, dass Sie eine Anti-Vorlage für das Code- / Projektmanagement in zweierlei Hinsicht benötigen: Kategorisierung von Modulen (Java-Bits unter Java-Knoten, Perl unter Perl-Knoten) und ein Projekt mit Dateien an verschiedenen Speicherorten von wo aus der Entwickler sie visualisiert. Da git Hashes von Verzeichnisinhalten verwaltet, um zu sehen, was geändert wird, bricht dies auch git als solches.

Daemeon Reiydelle

Daemeon
quelle