2010-11-12 15 views
22

Ich habe git-svn verwendet, um eine git Spiegel eines SVN-Repository zu erstellen. Die Struktur innerhalb des SVN war etwas abweichend, also hat git einen Zweig erstellt, der keinen gemeinsamen Commit mit dem Zweig master hat.git - Setzen eines Commit Eltern ohne Rebase

 A---B---C topic 

D---E---F---G master 

ich, dass A zu begehen wissen basiert weg begehen E und ich bin ziemlich zuversichtlich, dass ich die Probleme behoben haben verursacht git nicht, diese Tatsache zu erkennen (mit filter-branch). Was ich tun möchte, ist topic zum master Zweig erneut befestigen, E als Mutter von A Einstellung:

 A---B---C topic 
    /
D---E---F---G master 

git-rebase scheint nicht, für mich zu arbeiten, weil der Unterschied für A Listen die Schaffung eines commit ganze Menge von Dateien, die bereits in master existieren, was zu einer großen Anzahl von Konflikten führt.
Von meinem Verständnis von Git nur Einstellung E als Eltern von A sollte genug sein, um alle Probleme zu lösen.
Ist das möglich? Wenn es ist, wie kann ich es tun?

+0

Jede Chance, den Git-Spiegel der Svn-Zeige "Zweige" in das richtige Verzeichnis neu zu initiieren? Oder die SVN-Struktur zuerst reparieren? – stefanw

+0

Tatsächlich verwendete das Repo das Standardstamm/Tag/Zweig-Layout. Der Zweig, den ich reparieren wollte, wurde jedoch erstellt, indem nur ein Unterpfad von trunk kopiert wurde - das war ein bisschen zu viel für git-svn. –

+0

Rebase hat eine 'root' Option. Verwenden Sie das mit den On- und Preserve-Merges, wenn Sie es brauchen. –

Antwort

28

Werfen Sie einen Blick auf Transplantate (die Graft-Datei kann in .git/info/grafts gefunden werden). Das Format ist ziemlich einfach:

<commit sha1> <parent1 sha1> <parent2 sha1> … <parentN sha1> 

Das macht git glauben, dass ein Commit andere Eltern hat, als es tatsächlich hat. Verwenden Sie Filter-Zweig zu Transplantate dauerhaft zu machen (so kann die Datei Transplantate entfernt werden):

git filter-branch --tag-name-filter cat -- --all 

Beachten Sie, dass diese umschreibt Geschichte des Repository, so sollte nicht auf gemeinsames repos verwendet werden!


Wenn Sie nur die Geschichte der Commits neu zu schreiben, die auf den Master-Zweig gepfropft werden, zum Beispiel, verwenden Sie diesen Befehl:

git filter-branch --tag-name-filter cat -- master.. 
+0

Verwenden Sie keine Transplantate oder Filter-Zweig, wenn Sie nicht müssen. –

+3

Grafts sind unglaublich nützlich, wenn Sie sie brauchen, aber wie einige andere Funktionen in Git sollten sie verwendet werden, bevor Sie das Repo freigeben (oder Sie müssen alle anderen dazu bringen, erneut zu klonen). Wie die Antwort sagt, erstellen Sie einfach die Grafts-Datei (Hash-of-A, Leerzeichen, Hash-of-E, Newline) und verwenden Sie "git filter-branch - Tag-Name-Filter cat - all" um neu zu schreiben Geschichte, ohne andere Commit-Daten zu ändern – JodaStephen

+0

@JodaStephen sollten Sie das zur Antwort hinzufügen. Weißt du, ob es in Ordnung ist, das zu tun, wenn das Repository veröffentlicht wird, aber die Transplantationen, mit denen du dich beschäftigst, berühren nur neue, unveröffentlichte Commits? – naught101

8

Basierend auf Ihre Diagramme (obwohl ich bin Bedenken Sie, was Sie mit "Ich bin ziemlich positiv, dass ich die Probleme behoben habe, die dazu führen, dass git diese Tatsache nicht erkennt (unter Verwendung von filter-branch)."), sollten Sie in der Lage sein, etwas wie das Folgende zu tun.

# checkout A 
git checkout A 

# Reset the branch pointer to E so that E is the parent of the next commit 
# --soft ensures that the index stays the same 
git reset --soft E 

# Remake the commit with the E as the parent, re-using the old commit metadata 
git commit -C [email protected]{1} 

# Rebase the topic branch onto the modified A commit (current HEAD) 
git rebase --onto HEAD A topic 
+0

Funktioniert fast gut, aber Thema endet nicht nach dem Vorgang die Remote-Herkunft/Thema zu verfolgen! –

5

Alles, was Sie brauchen dies:

git rebase --root --onto master^^ topic^^ topic 

die Wurzel Option können Sie A.

UPDATE umfassen:

Fügen Sie die --preserve-merges Option, wenn Sie die Verzweigung behalten wollen und Verschmelzung des Teils, den Sie reversieren.

+1

Dieser Befehl funktionierte perfekt für mich! – jarvisschultz

+0

Das funktioniert gut, wenn Sie eine lineare Historie haben, wenn es Merge-Commits hat, müssen Sie '-Preserve-Merges' verwenden, und Sie müssen Merge-Konflikte manuell wieder auflösen. – Flimm

+0

Ja. Ich werde die Antwort aktualisieren. Ein anderes Mal, dass ich die gleiche Frage beantwortet habe, habe ich diese Option eingeschlossen. –