it-swarm.com.de

Checkout-Unterverzeichnisse in Git?

Ist es möglich, Unterverzeichnisse eines Repositorys in Git auszuchecken?

Stellen Sie sich vor, ich richte eine neue WordPress Installation ein. Ich werde zwei neue Verzeichnisse für meine Plugin- und Theme-Anpassung erstellen:

  • wordpress/wp-content/plugins/myplugins/
  • wordpress/wp-content/themes/mytheme/

Ich möchte diese Verzeichnisse über Git pflegen. In Subversion würde ich dies erreichen, indem ich trunk/myplugins/ und trunk/mytheme/ Verzeichnisse und Auschecken von Unterverzeichnissen. Hat Git eine Möglichkeit, dieselbe Aufgabe mit einem einzigen Repository auszuführen?

Ich könnte nur das Boot auf einem Git-Paradigma vermissen, als langjähriger SVN-Benutzer mit wenig Kontakt zu Git.

Bearbeiten: Mehrere Zweige Das Speichern verschiedener Inhalte ist eine interessante Möglichkeit, dies zu handhaben.

150

Sparse Checkout sind jetzt in Git 1.7 .

Siehe auch die Frage " Ist es möglich, ein spärliches Auschecken durchzuführen, ohne zuerst das gesamte Repository auszuchecken? ".

Beachten Sie, dass Sie für spärliche Auscheckvorgänge immer noch download das gesamte Repository benötigen, obwohl einige der von Git heruntergeladenen Dateien nicht in Ihrem Arbeitsbaum landen.

117
Collin Anderson

Es gibt keinen wirklichen Weg, das in git zu tun. Und wenn Sie als einzelne Arbeitseinheit keine Änderungen vornehmen, die beide Bäume gleichzeitig betreffen, gibt es keinen guten Grund, ein einziges Repository für beide zu verwenden. Ich dachte, ich würde diese Subversion-Funktion vermissen, aber ich fand heraus, dass das Erstellen von Repositorys so wenig administrativen Aufwand mit sich bringt (einfach aufgrund der Tatsache, dass Repositorys direkt neben ihrer Arbeitskopie gespeichert werden, anstatt dass ich explizit einen Ort außerhalb der Repositorys auswählen muss Arbeitskopie), an die ich mich gewöhnt habe, viele kleine Single-Purpose-Repositories zu erstellen.

Wenn Sie darauf bestehen (oder es wirklich brauchen), können Sie ein Git-Repository mit nur mytheme und myplugins Verzeichnissen erstellen und diese aus den WordPress) symbolisieren Installieren.


MDCore schrieb:

festschreiben, z. mein Thema erhöht die Revisionsnummer für myplugin

Beachten Sie, dass dies für git kein Problem darstellt, wenn Sie beide Verzeichnisse in einem einzigen Repository ablegen, da git das Konzept der monotonen Erhöhung von Revisionsnummern jeglicher Form gänzlich überflüssig macht.

Das einzige Kriterium für die Zusammenstellung von Dingen in einem einzelnen Repository in git ist, ob es sich um eine einzelne Einheit handelt, d. H. In Ihrem Fall, ob es Änderungen gibt, bei denen es nicht sinnvoll ist, die Änderungen in jedem Verzeichnis einzeln zu betrachten. Wenn Sie Änderungen haben, bei denen Sie Dateien in beiden Verzeichnissen gleichzeitig bearbeiten müssen und die Änderungen zusammen gehören, sollten sie ein Repository sein. Wenn nicht, dann trage sie nicht zusammen.

Git möchte wirklich, dass Sie separate Repositorys für separate Entitäten verwenden.

Submodule

Submodule erfüllen nicht den Wunsch, beide Verzeichnisse in einem Repository zu halten, da sie tatsächlich ein separates Repository für jedes Verzeichnis erzwingen , das dann zusammengeführt wird in einem anderen Repository mit Submodulen. Schlimmer noch, da die Verzeichnisse innerhalb der WordPress) -Installation keine direkten Unterverzeichnisse desselben Verzeichnisses sind und auch Teil einer Hierarchie mit vielen anderen Dateien sind, wobei die Verzeichnis-Repositorys als Submodule in einem einheitlichen Repository verwendet werden würde überhaupt keinen Nutzen bringen, da das einheitliche Repository keinen Anwendungsfall/Bedarf widerspiegeln würde.

17

Eine Sache, die ich an spärlichen Auschecken nicht mag, ist, dass Ihre Verzeichnisstruktur alle Verzeichnisse enthalten muss, die zu ihr führen, wenn Sie ein Unterverzeichnis auschecken möchten, das ein paar Verzeichnisse tief ist.

Wie ich das umgehen kann, ist das Klonen des Repos an einem Ort, der nicht mein Arbeitsbereich ist, und erstellen Sie dann eine symbolische Verknüpfung in meinem Arbeitsbereichsverzeichnis zum Unterverzeichnis im Repository. Git funktioniert ganz gut so, weil Dinge wie Git-Status die Änderungsdateien relativ zu Ihrem aktuellen Arbeitsverzeichnis anzeigen.

12
OleTraveler

Tatsächlich befinden sich "schmale" oder "teilweise" oder "spärliche" Kassen in der aktuellen, starken Entwicklung für Git. Beachten Sie, dass Sie unter .git Immer noch das vollständige Repository haben. Die anderen beiden Posts sind für den aktuellen Status von Git aktuell, aber es sieht so aus , als ob wir irgendwann in der Lage sein werden, spärliche Check-outs durchzuführen. Überprüfen Sie die Mailinglisten Wenn Sie an weiteren Details interessiert sind, ändern sich diese schnell.

10
Pat Notz

git clone --filter Ab Git 2.19

Diese Option überspringt das Abrufen nicht benötigter Objekte vom Server:

git clone --depth 1 --no-checkout --filter=blob:none \
  "file://$(pwd)/server_repo" local_repo
cd local_repo
git checkout master -- mdir/

Der Server sollte konfiguriert sein mit:

git config --local uploadpack.allowfilter 1
git config --local uploadpack.allowanysha1inwant 1

Ab v2.19.0 gibt es keine Serverunterstützung, diese kann jedoch bereits lokal getestet werden.

file://$(path) ist erforderlich, um git clone - Protokollverschiebungen zu überwinden: Wie wird ein lokales Git-Repository mit einem relativen Pfad flach geklont?

Denken Sie daran, dass --depth 1 Bereits --single-branch Impliziert, siehe auch: Wie klone ich einen einzelnen Zweig in Git?

TODO: --filter=blob:none Überspringt alle Blobs, ruft aber trotzdem alle Baumobjekte ab. Bei einem normalen Repo sollte dies jedoch im Vergleich zu den Dateien selbst winzig sein, sodass dies bereits gut genug ist. Gefragt unter: https://www.spinics.net/lists/git/msg342006.html Entwickler haben geantwortet, dass ein --filter=tree:0 In Arbeit ist, um dies zu tun.

Das Format von --filter Ist auf man git-rev-list Dokumentiert.

Das Git-Remote-Protokoll wurde erweitert, um diese Funktion zu unterstützen.

Dokumente zum Git-Tree:

Probieren Sie es aus

#!/usr/bin/env bash
set -eu

list-objects() (
  git rev-list --all --objects
  echo "master commit SHA: $(git log -1 --format="%H")"
  echo "mybranch commit SHA: $(git log -1 --format="%H")"
  git ls-tree master
  git ls-tree mybranch | grep mybranch
  git ls-tree master~ | grep root
)

# Reproducibility.
export GIT_COMMITTER_NAME='a'
export GIT_COMMITTER_EMAIL='a'
export GIT_AUTHOR_NAME='a'
export GIT_AUTHOR_EMAIL='a'
export GIT_COMMITTER_DATE='2000-01-01T00:00:00+0000'
export GIT_AUTHOR_DATE='2000-01-01T00:00:00+0000'

rm -rf server_repo local_repo
mkdir server_repo
cd server_repo

# Create repo.
git init --quiet
git config --local uploadpack.allowfilter 1
git config --local uploadpack.allowanysha1inwant 1

# First commit.
# Directories present in all branches.
mkdir d1 d2
printf 'd1/a' > ./d1/a
printf 'd1/b' > ./d1/b
printf 'd2/a' > ./d2/a
printf 'd2/b' > ./d2/b
# Present only in root.
mkdir 'root'
printf 'root' > ./root/root
git add .
git commit -m 'root' --quiet

# Second commit only on master.
git rm --quiet -r ./root
mkdir 'master'
printf 'master' > ./master/master
git add .
git commit -m 'master commit' --quiet

# Second commit only on mybranch.
git checkout -b mybranch --quiet master~
git rm --quiet -r ./root
mkdir 'mybranch'
printf 'mybranch' > ./mybranch/mybranch
git add .
git commit -m 'mybranch commit' --quiet

echo "# List and identify all objects"
list-objects
echo

# Restore master.
git checkout --quiet master
cd ..

# Clone. Don't checkout for now, only .git/ dir.
git clone --depth 1 --quiet --no-checkout --filter=blob:none "file://$(pwd)/server_repo" local_repo
cd local_repo

# List missing objects from master.
echo "# Missing objects after --no-checkout"
git rev-list --all --quiet --objects --missing=print
echo

echo "# Git checkout fails without internet"
mv ../server_repo ../server_repo.off
! git checkout master
echo

echo "# Git checkout fetches the missing directory from internet"
mv ../server_repo.off ../server_repo
git checkout master -- d1/
echo

echo "# Missing objects after checking out d1"
git rev-list --all --quiet --objects --missing=print

GitHub upstream .

Ausgabe in Git v2.19:

# List and identify all objects
c6fcdfaf2b1462f809aecdad83a186eeec00f9c1
fc5e97944480982cfc180a6d6634699921ee63ec
7251a83be9a03161acde7b71a8fda9be19f47128
62d67bce3c672fe2b9065f372726a11e57bade7e
b64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1
308150e8fddde043f3dbbb8573abb6af1df96e63 d1/a
f70a17f51b7b30fec48a32e4f19ac15e261fd1a4 d1/b
84de03c312dc741d0f2a66df7b2f168d823e122a d2
0975df9b39e23c15f63db194df7f45c76528bccb d2/a
41484c13520fcbb6e7243a26fdb1fc9405c08520 d2/b
7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master
8b25206ff90e9432f6f1a8600f87a7bd695a24af master/master
ef29f15c9a7c5417944cc09711b6a9ee51b01d89
19f7a4ca4a038aff89d803f017f76d2b66063043 mybranch
1b671b190e293aa091239b8b5e8c149411d00523 mybranch/mybranch
c3760bb1a0ece87cdbaf9a563c77a45e30a4e30e
a0234da53ec608b54813b4271fbf00ba5318b99f root
93ca1422a8da0a9effc465eccbcb17e23015542d root/root
master commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
mybranch commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
040000 tree b64bf435a3e54c5208a1b70b7bcb0fc627463a75    d1
040000 tree 84de03c312dc741d0f2a66df7b2f168d823e122a    d2
040000 tree 7d5230379e4652f1b1da7ed1e78e0b8253e03ba3    master
040000 tree 19f7a4ca4a038aff89d803f017f76d2b66063043    mybranch
040000 tree a0234da53ec608b54813b4271fbf00ba5318b99f    root

# Missing objects after --no-checkout
?f70a17f51b7b30fec48a32e4f19ac15e261fd1a4
?8b25206ff90e9432f6f1a8600f87a7bd695a24af
?41484c13520fcbb6e7243a26fdb1fc9405c08520
?0975df9b39e23c15f63db194df7f45c76528bccb
?308150e8fddde043f3dbbb8573abb6af1df96e63

# Git checkout fails without internet
fatal: '/home/ciro/bak/git/test-git-web-interface/other-test-repos/partial-clone.tmp/server_repo' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

# Git checkout fetches the missing directory from internet
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.

# Missing objects after checking out d1
?8b25206ff90e9432f6f1a8600f87a7bd695a24af
?41484c13520fcbb6e7243a26fdb1fc9405c08520
?0975df9b39e23c15f63db194df7f45c76528bccb

Schlussfolgerungen: Alle Blobs von außerhalb von d1/ Fehlen.

Beachten Sie, dass root/root Und mybranch/mybranch Ebenfalls fehlen, aber --depth 1 Dies aus der Liste der fehlenden Dateien verbirgt. Wenn Sie --depth 1 Entfernen, werden sie in der Liste der fehlenden Dateien angezeigt.

Wie Sie in Ihrer Bearbeitung feststellen, können Sie zwei separate Zweige zum Speichern der beiden separaten Verzeichnisse verwenden. Auf diese Weise bleiben beide im selben Repository, es können jedoch keine Commits über beide Verzeichnisbäume ausgeführt werden. Wenn Sie eine Änderung in der einen haben, die eine Änderung in der anderen erfordert, müssen Sie diese als zwei separate Festschreibungen ausführen, und Sie eröffnen die Möglichkeit, dass zwei Auscheckvorgänge der beiden Verzeichnisse nicht mehr synchron sind.

Wenn Sie das Verzeichnispaar als eine Einheit behandeln möchten, können Sie 'wordpress/wp-content' als Stammverzeichnis Ihres Repos verwenden und die .gitignore-Datei auf der obersten Ebene verwenden, um alles außer den beiden relevanten Unterverzeichnissen zu ignorieren. Dies ist an dieser Stelle wahrscheinlich die vernünftigste Lösung.

Angeblich kommen seit zwei Jahren spärliche Kassen, aber es gibt noch keine Anzeichen dafür im Git-Entwicklungs-Repo und auch keine Anzeichen dafür, dass die notwendigen Änderungen jemals dort eintreffen werden. Ich würde mich nicht auf sie verlassen.

1
Curt J. Sampson

Sie können kein einzelnes Verzeichnis eines Repository auschecken, da das gesamte Repository vom einzelnen .git-Ordner im Stammverzeichnis des Projekts verwaltet wird, anstatt von Subvers unzähligen .svn-Verzeichnissen.

Das Problem bei der Arbeit an Plugins in einem einzelnen Repository ist, dass das Festschreiben von zB mytheme die Revisionsnummer für myplugin erhöht, also auch in Subversion Es ist besser, separate Repositorys zu verwenden.

Das Subversion-Paradigma für Unterprojekte lautet svn: externals , was in git etwas submodules bedeutet (aber nicht genau, falls Sie zuvor svn: externals verwendet haben).

1
MDCore