2010 Stimmen

Subverzeichnis in eigenes Git-Repository auslagern

Ich habe ein Git-Repository, das eine Reihe von Unterverzeichnissen enthält. Jetzt habe ich festgestellt, dass eines der Unterverzeichnisse nicht mit den anderen zusammenhängt und in ein separates Repository abgetrennt werden sollte.

Wie kann ich das tun, während ich die Historie der Dateien innerhalb des Unterverzeichnisses beibehalte?

Ich könnte vermutlich einen Klon erstellen und die unerwünschten Teile jedes Klon entfernen, aber ich nehme an, dass dies mir den vollständigen Baum liefern würde, wenn ich eine ältere Revision herausnehme usw. Dies mag akzeptabel sein, aber ich möchte lieber so tun, als ob die beiden Repositories keine gemeinsame Historie haben.

Nur zur Klarstellung, ich habe folgende Struktur:

XYZ/
    .git/
    XY1/
    ABC/
    XY2/

Aber ich möchte stattdessen das hier:

XYZ/
    .git/
    XY1/
    XY2/
ABC/
    .git/
    ABC/

10 Stimmen

Das ist jetzt trivial mit git filter-branch siehe meine Antwort unten.

16 Stimmen

@jeremyjjbrown hat recht. Es ist zwar nicht mehr schwierig dies zu tun, aber es ist schwierig, die richtige Antwort auf Google zu finden, da die alten Antworten die Ergebnisse dominieren.

4 Stimmen

Die Verwendung von git filter-branch wird abgeraten. Siehe Warnung in der Dokumentation.

40voto

Simon A. Eugster Punkte 3940

Bearbeiten: Bash-Skript hinzugefügt.

Die hier gegebenen Antworten haben bei mir nur teilweise funktioniert; Viele große Dateien blieben im Cache. Was letztendlich funktioniert hat (nach Stunden in #git on freenode):

git clone --no-hardlinks file:///QUELLE /tmp/blubb
cd blubb
git filter-branch --subdirectory-filter ./PFAD_ZUM_EXTRAKT --prune-empty --tag-name-filter cat -- --all
git clone file:///tmp/blubb/ /tmp/blooh
cd /tmp/blooh
git reflog expire --expire=now --all
git repack -ad
git gc --prune=now

Mit den vorherigen Lösungen betrug die Größe des Repositories etwa 100 MB. Diese hier hat sie auf 1,7 MB reduziert. Vielleicht hilft es jemandem :)


Das folgende Bash-Skript automatisiert die Aufgabe:

!/bin/bash

if (( $# < 3 ))
then
    echo "Verwendung:   $0   "
    echo
    echo "Beispiel: $0 /Projekte/42.git erste/antwort/ ersteAntwort"
    exit 1
fi

clone=/tmp/${3}Klon
newN=/tmp/${3}

git clone --no-hardlinks file://$1 ${clone}
cd ${clone}

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

git clone file://${clone} ${newN}
cd ${newN}

git reflog expire --expire=now --all
git repack -ad
git gc --prune=now

27voto

jeremyjjbrown Punkte 7513

Dies ist nicht mehr so komplex, Sie können einfach den git filter-branch Befehl auf einem Klon Ihres Repositories verwenden, um die Unterverzeichnisse zu entfernen, die Sie nicht möchten, und dann auf den neuen Remote zu pushen.

git filter-branch --prune-empty --subdirectory-filter  master
git push  -f .

4 Stimmen

Dies hat wie ein Zauber funktioniert. YOUR_SUBDIR im obigen Beispiel ist das Unterverzeichnis, das Sie BEHALTEN möchten, alles andere wird entfernt.

1 Stimmen

Aktualisierungen basierend auf Ihrem Kommentar.

3 Stimmen

Das beantwortet die Frage nicht. Aus den Dokumenten geht hervor, dass Das Ergebnis wird dieses Verzeichnis (und nur dieses) als sein Projekt-Stammverzeichnis enthalten. und tatsächlich ist das, was du bekommst, d.h. die ursprüngliche Projektstruktur wird nicht beibehalten.

19voto

Anthony O. Punkte 18951

Hier ist eine kleine Änderung an CoolAJ86's "The Easy Way™" Antwort, um mehrere Unterordner (sagen wir sub1 und sub2) in ein neues Git-Repository aufzuteilen.

The Easy Way™ (mehrere Unterordner)

  1. Bereiten Sie das alte Repository vor

    pushd 
    git filter-branch --tree-filter "mkdir ; mv   /" HEAD
    git subtree split -P  -b 
    popd

    Hinweis: darf keine führenden oder abschließenden Zeichen enthalten. Zum Beispiel muss der Ordner mit dem Namen subproject als subproject übergeben werden, NICHT als ./subproject/

    Hinweis für Windows-Benutzer: wenn Ihre Ordner tiefer als Stufe 1 sind, muss den *nix-Stil Ordner-Trennzeichen (/) enthalten. Zum Beispiel muss der Ordner mit dem Namen path1\path2\subproject als path1/path2/subproject übergeben werden. Verwenden Sie außerdem nicht den Befehl mv, sondern move.

    Abschließender Hinweis: Der einzige und große Unterschied zur Grundantwort ist die zweite Zeile des Skripts "git filter-branch..."

  2. Erstellen Sie das neue Repository

    mkdir 
    pushd 
    
    git init
    git pull  
  3. Verknüpfen Sie das neue Repository mit Github oder wo auch immer

    git remote add origin 
    git push origin -u master
  4. Bereinigung, wenn gewünscht

    popd # raus aus 
    pushd 
    
    git rm -rf 

    Hinweis: Dies hinterlässt alle historischen Verweise im Repository. Siehe den Anhang in der Originalantwort, wenn Sie tatsächlich besorgt sind, dass ein Passwort commito wurde oder Sie die Dateigröße Ihres .git-Ordners verringern müssen.

1 Stimmen

Dies hat für mich mit geringfügigen Änderungen funktioniert. Weil meine sub1 und sub2 Ordner in der ursprünglichen Version nicht existierten, musste ich mein --tree-filter Skript wie folgt ändern: "mkdir ; if [ -d sub1 ]; then mv /; fi". Für den zweiten filter-branch Befehl ersetzte ich durch , ließ die Erstellung von weg und fügte -f nach filter-branch ein, um die Warnung einer vorhandenen Sicherung zu überschreiben.

0 Stimmen

Dies funktioniert nicht, wenn sich eines der Unterverzeichnisse im Verlauf von Git geändert hat. Wie kann das gelöst werden?

0 Stimmen

@nietras sieh dir die Antwort von rogerdpack an. Hat mich eine Weile gekostet, sie zu finden, nachdem ich alle Informationen in diesen anderen Antworten gelesen und aufgenommen hatte.

19voto

D W Punkte 2889

Aktualisierung: Das git-subtree-Modul war so nützlich, dass das Git-Team es in den Kern integrierte und es zu git subtree machte. Hier sehen: Teilverzeichnis (verschieben) in ein separates Git-Repository auskoppeln

git-subtree könnte hierfür nützlich sein

http://github.com/apenwarr/git-subtree/blob/master/git-subtree.txt (veraltet)

http://psionides.jogger.pl/2010/02/04/code-sharing-between-projects-with-git-subtree/

1 Stimmen

Git-subtree ist jetzt Teil von Git, obwohl es im contrib-Baum liegt und daher nicht immer standardmäßig installiert ist. Ich weiß, dass es durch die Homebrew Git-Formel installiert ist, aber ohne seine man-Seite. apenwarr bezeichnet seine Version daher als veraltet.

13voto

MM. Punkte 1917

Die ursprüngliche Frage möchte XYZ/ABC/(*Dateien) in ABC/ABC/(*Dateien) umwandeln. Nach Umsetzung der akzeptierten Antwort für meinen eigenen Code habe ich festgestellt, dass es tatsächlich XYZ/ABC/(*Dateien) in ABC/(*Dateien) ändert. Sogar die filter-branch Man-Seite sagt:

Das Ergebnis wird diesen Ordner enthalten (und nur diesen) als sein Projektwurzelverzeichnis."

Mit anderen Worten, es befördert den Top-Level-Ordner "nach oben" um eine Ebene. Das ist ein wichtiger Unterschied, denn zum Beispiel in meiner Historie hatte ich einen Top-Level-Ordner umbenannt. Indem Ordner "nach oben" um eine Ebene befördert werden, verliert git die Kontinuität am Commit, an dem ich die Umbenennung durchgeführt habe.

Ich habe die Kontinuität nach filter-branch verloren

Meine Antwort auf die Frage ist daher, 2 Kopien des Repositorys zu erstellen und manuell den/die Ordner zu löschen, die Sie in jedem behalten möchten. Die Man-Seite unterstützt mich dabei:

[...] Vermeiden Sie die Verwendung [dieses Befehls], wenn ein einfacher einzelner Commit ausreichen würde, um Ihr Problem zu beheben

1 Stimmen

Ich mag den Stil dieses Diagramms. Darf ich fragen, welches Tool du benutzt?

3 Stimmen

Turm für Mac. Ich mag es wirklich. Es ist fast wert, allein auf Mac umzusteigen.

2 Stimmen

Ja, obwohl in meinem Fall mein untergeordneter targetdir zu einem bestimmten Zeitpunkt umbenannt worden war und git filter-branch einfach aufgehört hat, alle vor der Umbenennung gemachten Commits zu löschen! Schockierend, wenn man bedenkt, wie geschickt Git darin ist, solche Dinge zu verfolgen und sogar die Migration einzelner Inhaltsfragmente!

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X