2010-11-12 13 views
22

Użyłem git-svn do utworzenia lustra git z repozytorium SVN. Struktura wewnątrz SVN była trochę poza standardem, więc git stworzył gałąź, która nie ma wspólnego z podziałem na gałąź master.git - ustawianie elementu macierzystego commit bez podstawy bazy

 A---B---C topic 

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

wiem, że zobowiązują A opiera się popełnić E i jestem całkiem pewny, że Naprawiłem problemy powodujące git nie uznać tego faktu (używając filter-branch). Co chcę zrobić to ponownie załączyć topic do master branży, ustanawiając E jako rodzica A:

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

git-rebase nie wydają się działać dla mnie, bo diff do popełnienia A list stworzenia cała masa plików, które już istnieją w master, co powoduje ogromną liczbę konfliktów.
Z mojego rozumienia gita samo ustawienie E jako rodzica A powinno wystarczyć, aby rozwiązać wszystkie problemy.
Czy to możliwe? Jeśli tak, jak mogę to zrobić?

+0

Czy istnieje szansa na ponowne zainicjowanie git mirror dla svn wskazując "branches" w prawym katalogu? Albo najpierw ustalając strukturę svn? – stefanw

+0

W rzeczywistości repo wykorzystywał standardowy układ trunk/tags/branches. Jednak gałąź, którą próbowałem naprawić, została stworzona przez skopiowanie tylko ścieżki podrzędnej pnia - zgadnij, że było to trochę za dużo dla obsługi git-svn. –

+0

rebase ma opcję 'root'. Użyj tego z 'na' i' zachowaj-scalenia', jeśli potrzebujesz. –

Odpowiedz

28

Spójrz na przeszczepy (plik przeszczepu można znaleźć w .git/info/grafts). Format jest dość prosta:

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

To sprawia, że ​​git uwierzyć, że ma różne zobowiązać rodziców niż to faktycznie ma. Użyj filtra oddziałem aby przeszczepy stały (tak plik przeszczepy mogą być usunięte):

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

Zauważ, że ta historia przepisuje z repozytorium, więc nie powinny być stosowane na wspólnych repo!


Jeśli tylko chcą przepisać historię zatwierdzeń, które są szczepione na gałęzi głównej, na przykład, użyj polecenia:

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

nie używaj przeszczepów lub gałęzi filtra, jeśli nie musisz. –

+3

Przeszczepy są niezwykle użyteczne, ponieważ są potrzebne, ale podobnie jak niektóre inne funkcje w git powinny być użyte przed udostępnieniem repo (lub musisz nakłonić wszystkich do ponownego sklonowania). Jak mówi odpowiedź, po prostu stwórz plik przeszczepów (hash-of-A, spacja, hash-of-E, newline) i użyj "git filter-branch --tag-name-filter cat - --all" do przepisania historia bez zmiany innych danych zatwierdzenia – JodaStephen

+0

@JodaStephen powinieneś dodać to do odpowiedzi. Czy wiesz, czy można to zrobić, jeśli repozytorium zostanie opublikowane, ale przeszczepy, z którymi masz do czynienia, dotykają tylko nowych, niepublikowanych zatwierdzeń? – naught101

8

Na podstawie diagramów (chociaż jestem zaniepokojony tym, co masz na myśli przez "Jestem całkiem pozytywny, że naprawiłem problemy powodujące, że git nie rozpoznaje tego faktu (używając filter-branch)."), powinieneś być w stanie zrobić coś takiego.

# 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

Działa prawie bez zarzutu, ale temat kończy się nie śledzeniem zdalnego pochodzenia/tematu po tej operacji! –

5

Wszystko czego potrzebujesz to:

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

opcja korzeń pozwala m.in. A.

UPDATE:

Dodaj opcję --preserve-merges jeśli chcesz zachować rozgałęzienia i scalenie części, która się zmienia.

+1

To polecenie działało idealnie dla mnie! – jarvisschultz

+0

Działa to świetnie, jeśli posiadasz liniową historię, jeśli ma ona scalone zatwierdzenia, musisz użyć '--preserve-merges', i musisz ręcznie rozwiązać konflikty scalania. – Flimm

+0

Tak. Zaktualizuję odpowiedź. Innym razem, gdy odpowiedziałem na to samo pytanie, uwzględniłem tę opcję. –