Wie kann ich ein Verzeichnis und Dateien zusammen mit dem Commit-Verlauf in ein Unterverzeichnis verschieben?
Zum Beispiel:
-
Quellverzeichnisstruktur:
[project]/x/[files & sub-dirs]
-
Zielverzeichnisstruktur:
[project]/x/p/q/[files & sub-dirs]
erste.ptl
Wie kann ich ein Verzeichnis und Dateien zusammen mit dem Commit-Verlauf in ein Unterverzeichnis verschieben?
Zum Beispiel:
Quellverzeichnisstruktur: [project]/x/[files & sub-dirs]
Zielverzeichnisstruktur: [project]/x/p/q/[files & sub-dirs]
VonC
Um den Kommentar von bmargulies zu ergänzen, lautet die vollständige Sequenz:
mkdir -p x/p/q # make sure the parent directories exist first
git mv x/* x/p/q # move folder, with history preserved
git commit -m "changed the foldername x into x/p/q"
Probieren Sie es zuerst aus, um eine Vorschau des Umzugs zu sehen:
git mv -n x/* x/p/q
Wolfgang kommentiert:
Wenn Sie bash verwenden, können Sie das Problem vermeiden, dass Sie versuchen, einen Ordner in sich selbst zu verschieben, indem Sie einen erweiterten Glob wie diesen verwenden (mit der
shopt
eingebaut):
shopt -s extglob; git mv !(folder) folder
Captain Man berichtet in den Kommentaren zu tun:
mkdir temp
git mv x/* temp
mkdir -p x/p/q
git mv temp x/p/q
rmdir temp;
Kontext:
Ich bin auf Windows mit Cygwin.
Mir wurde gerade klar, dass ich das getan habeshopt -s extglob
Beispiel falsch, also war mein Weg vielleicht nicht notwendig, aber ich verwende normalerweise zsh anstelle von bash, und es hatte nicht den Befehlshopt -s extglob
(obwohl ich mir sicher bin, dass es eine Alternative gibt), also sollte dieser Ansatz Shell-übergreifend funktionieren (Subbing in Ihrer Shellmkdir
undrmdir
wenn es besonders fremd ist)
Als Alternative erwähnt spanky in den Kommentaren die -k
Option von git mv
:
Aktionen zum Verschieben oder Umbenennen überspringen, die zu einer Fehlerbedingung führen würden.
git mv -k * target/
Das würde die “can not move directory into itself
” Error.
Du kannst dich nicht bewegen x
in ein Unterverzeichnis von sich selbst. git mv ...
macht den Job, muss nicht git add ...
nichts, wenn es keine weiteren Änderungen gibt.
– Vonbrand
4. Februar 2014 um 18:28 Uhr
Wie verwende ich hier git mv? Es beschwert sich, dass ich ein Verzeichnis nicht in ein Unterverzeichnis von sich selbst verschieben kann.
– Abhinav Manchanda
18. Oktober 2015 um 22:38 Uhr
Wenn Sie Bash verwenden, können Sie das Problem vermeiden, einen Ordner in sich selbst zu verschieben, indem Sie einen erweiterten Glob wie folgt verwenden: shopt -s extglob; git mv !(folder) folder
–Wolfgang
16. November 2015 um 19:17 Uhr
Ich habe gerade erfahren, dass Sie verwenden können git mv -k * target/
um den Fehler “Verzeichnis kann nicht in sich selbst verschoben werden” zu vermeiden.
– Spanky
7. August 2017 um 21:20 Uhr
@Spanky Interessant. Ich habe Ihren Kommentar zur besseren Sichtbarkeit in die Antwort aufgenommen.
– VonC
7. August 2017 um 21:40 Uhr
PiQuer
Git leistet sehr gute Arbeit, um Inhalte zu verfolgen, auch wenn sie verschoben werden git mv
ist eindeutig der richtige Weg, wenn Sie Dateien verschieben, weil sie früher dazu gehörten x
aber jetzt gehören sie rein x/p/q
weil sich das Projekt so entwickelt hat.
Manchmal gibt es jedoch einen Grund, Dateien im Verlauf eines Projekts in ein Unterverzeichnis zu verschieben. Zum Beispiel, wenn die Dateien versehentlich irgendwo abgelegt wurden und seitdem einige weitere Commits durchgeführt wurden, aber die intermittierenden Commits keinen Sinn ergeben, wenn die Dateien am falschen Ort sind. Wenn das alles in einem lokalen Zweig passiert ist, wollen wir das Chaos aufräumen, bevor wir pushen.
Die Frage lautet “zusammen mit dem Commit-Verlauf”, was ich als Umschreiben des Verlaufs auf genau diese Weise interpretieren würde. Dies kann mit erfolgen
git filter-branch --tree-filter "cd x; mkdir -p p/q; mv [files & sub-dirs] p/q" HEAD
Die Dateien erscheinen dann im p/q
Unterverzeichnis im gesamten Verlauf.
Der Baumfilter eignet sich gut für kleine Projekte, sein Vorteil ist, dass der Befehl einfach und leicht verständlich ist. Für große Projekte lässt sich diese Lösung nicht sehr gut skalieren. Wenn es auf die Leistung ankommt, sollten Sie einen Indexfilter verwenden, wie in dieser Antwort beschrieben.
Bitte beachten Sie, dass das Ergebnis nicht auf einen öffentlichen Server gepusht werden sollte, wenn das Umschreiben Commits berührt, die bereits zuvor gepusht wurden.
danke, hat mir den tag versüßt! Ich wollte alle Dateien eines Baumes in ein neues Unterverzeichnis “verschieben” und habe deinen Ansatz mit genutzt mv * ./the-subdir
bekam aber den Fehler: “the-subdir kann nicht in ein Unterverzeichnis von sich selbst verschoben werden. Meine Lösung ist zu verwenden mv the-subdir /tmp; mv * /tmp/the-subdir mv /tmp/the-subdir ./
innerhalb des Baumfilterbefehls. Klappt wunderbar.
– Alexander
22. Mai 2014 um 7:40 Uhr
Ich könnte das nicht zum Laufen bringen, wenn ich nicht git mv [files & sub-dirs] p/q
anstatt ein Raw zu nennen mv
; Läuft auf einem Mac. Aber es hat am Ende gut für mich funktioniert, also danke!
– d4vidi
19. Februar 2018 um 16:51 Uhr
ich benutzte mv * .* the/subdir/ || true
Dateien und Punktdateien zu verschieben und die Fehlermeldungen zu ignorieren.
– joeytwiddle
18. Oktober 2019 um 10:21 Uhr
peroyhav
Ich sehe, dass dies eine alte Frage ist, aber ich fühle mich dennoch verpflichtet, mit meiner aktuellen Lösung des Problems zu antworten, die ich aus einem der Beispiele in abgeleitet habe Git-Buch. Anstatt ein ineffizientes zu verwenden --tree-filter
Ich schiebe die Dateien direkt auf den Index mit an --index-filter
.
git filter-branch -f --index-filter 'PATHS=`git ls-files -s | sed "s/^<old_location>/<new_location>/"`;GIT_INDEX_FILE=$GIT_INDEX_FILE.new; echo -n "$PATHS" | git update-index --index-info && if [ -e "$GIT_INDEX_FILE.new" ]; then mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"; fi' -- --all
Dies ist eine Spezialisierung eines der Beispiele aus dem Buch. Ich habe das gleiche Beispiel auch verwendet, um in einem speziellen Fall Dateien in der Commit-Historie massenhaft umzubenennen. wenn Sie Dateien in Unterverzeichnisse verschieben: Denken Sie daran, das /-Zeichen in den Pfaden mit einem \ zu maskieren, damit der sed-Befehl wie erwartet funktioniert.
Beispiel:
Project Directory
|-a
| |-a1.txt
| |-b
| | |-b1.txt
So verschieben Sie das b-Verzeichnis in das Projektstammverzeichnis:
git filter-branch -f --index-filter 'PATHS=`git ls-files -s | sed "s/a\/b\//b\//"`;GIT_INDEX_FILE=$GIT_INDEX_FILE.new; echo -n "$PATHS" | git update-index --index-info && if [ -e "$GIT_INDEX_FILE.new" ]; then mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"; fi' -- --all
Ergebnis:
Project Directory
|-a
| |-a1.txt
|
|-b
| |-b1.txt
Mit Ihrer Befehlszeile habe ich fatal: malformed index info -n 100644
. Mit git filter-branch -f --index-filter 'git ls-files -s | sed "s/<old_location>/<new_location>/" | GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info && mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD
es hat in meinem Fall funktioniert. Vergessen Sie nicht zu entkommen /
mit \/
.
– Tanguy_k
25. Februar 2019 um 23:10 Uhr
@tanguy_k Wenn Sie verwenden :
als Trennzeichen für sed
dann müssen Sie sich keine Sorgen um die Flucht machen /
.
– Mateen Ulhaq
2. Oktober 2019 um 23:43 Uhr
Der Befehl git mv ist der einfachste Weg. Zumindest auf meiner Linux-Box musste ich jedoch das Flag -k angeben, um zu vermeiden, dass eine Fehlermeldung zurückgegeben wird, dass ein Ordner nicht in sich selbst verschoben werden kann. Ich konnte die Aktion ausführen, indem ich …
mkdir subdirectory
git mv -k ./* ./subdirectory
# check to make sure everything moved (see below)
git commit
Als Warnung wird dies übersprungen alle Verschiebungen, die zu einem Fehlerzustand führen würden, daher möchten Sie wahrscheinlich überprüfen, ob nach der Verschiebung und vor einem Commit alles richtig funktioniert hat.
Hier ist ein alternativer Weg, wenn Sie aus irgendeinem Grund den Befehl git mv nicht verwenden möchten:
Stellen Sie sicher, dass Sie keine nicht festgeschriebenen Änderungen haben.
Git-Status
Verschieben Sie einfach den Ordner, der den .git-Ordner enthält, in den neuen Ordner:
mkdir neuer_ordner mv alter_ordner neuer_ordner
Verschieben Sie dann die .git old_folder aus dem verschobenen Ordner zurück in den Basisordner:
mv neuer_ordner/alter_ordner/.git neuer_ordner/
Stellen Sie dann alle erkannten Änderungen bereit und schreiben Sie sie fest (aufgeführt als Hinzufügen von Dateien zu ihrem neuen Speicherort und Entfernen von Dateien von ihrem alten Speicherort).
Eduard Falk
Mein eigener Vorschlag: git fast-export
Bearbeiten Sie dann die Exportdatei git fast-import
.
Ich verstehe die meisten Antworten auf diese Frage nicht, ich habe alle Möglichkeiten ausprobiert, ich habe immer entweder einen Fehler bekommen oder einfach nichts passiert, also habe ich einfach den .git-Ordner ausgeschnitten und in einen Unterordner eingefügt … weißt du was? Es funktionierte!
– Ayyash
6. Dezember 2016 um 11:11 Uhr
Siehe verwandte/doppelte Frage stackoverflow.com/q/33002612/421049. Meine Antwort stackoverflow.com/a/50547331/421049 behandelt dort Windows.
– Garret Wilson
26. Mai 2018 um 22:05 Uhr
Weiß jemand wie man es andersherum macht. Haben Sie eine Repro in einem Unterordner und fügen Sie dieser Repro dann einige übergeordnete Dateien/Ordner hinzu?
– Martin Krung
20. August 2018 um 11:26 Uhr