2013-01-09 13 views
5

ho importato un repository Bazaar in Git (usando git bzr), ma il repository risultante contiene un link genitore spuria commettere:Rimuovere spuria commettere puntatore genitore

Spurious parent link

Si noti che il commit tagged 1.02-6 è basato il 1.02-3 commit, ma 1.02-1 viene inoltre contrassegnato come genitore. (Nota: Tutti i commit in questa parte del pronti contro termine sono contrassegnati, non ci sono commit tra quelli mostrati.)

ho provato rebasing in diversi modi (sul ramo master: git rebase 1.02-3, git rebase -i upstream-1.02, git rebase --onto 1.02-1 1.02-3, git rebase --root upstream-1.02 --onto=other_branch) , ma in ogni caso fallisce con un conflitto di fusione. Questi sembrano tentare più del necessario; la cronologia è corretta eccetto per un puntatore genitore aggiuntivo registrato nel commit con tag 1.02-6.

Come si rimuove il collegamento per linearizzare la cronologia? C'è un modo migliore rispetto alla selezione manuale di tutti i commit in sequenza?

+1

È davvero "spurio"? Oppure c'erano correzioni di bug fatte a '1.02-1' che sono state unite in' 1.02-6' ma non sono state convertite in '1.02-3' (o sono state rese disponibili tramite un percorso diverso)? Non che abbia familiarità con 'bzr', e presumo che il grafico sopra sia semplificato solo per le versioni con tag (cioè ci sono altri commit/changeset tra di loro che non sono mostrati al momento). – twalberg

+0

@twalberg: non semplificato. Questi sono tutti i commit. –

+0

Potrebbe essere utile: http://git-scm.com/docs/git-commit-tree, 'git cat-file -p 1.02-6' –

risposta

5

È possibile eseguire manualmente il comando interno git commit-tree.

Vogliamo modificare il commit con tag 1.02-6 per rimuovere il puntatore genitore spurio (su 56a2f3b5948ab54c9239c2b384a6ea9eb1f410c4).

In primo luogo, leggere le informazioni dall'oggetto commettere esistente:

[email protected]:/path/repo.git$ git cat-file -p 1.02-6 
tree c658aa1ebcf2bf2a607696c7868b875be72fb01f 
parent 56a2f3b5948ab54c9239c2b384a6ea9eb1f410c4 
parent 4e671bf1d2298729c9e5cfd8229051cfe2c40831 
author James Damour (Suvarov454) <[email protected]> 1146319620 -0400 
committer Bazaar Package Importer <[email protected]> 1146319620 -0400 

The "main/" in the Section line of debian/control should be assumed. 

Extract the commit message using git log --format=%B -n 1 1.02-6.

Ora crea un nuovo commit con lo stesso contenuto (escluso il collegamento padre spuria, e le informazioni committer):

git log --format=%B -n 1 1.02-6 | \ 
    GIT_AUTHOR_NAME="James Damour (Suvarov454)" \ 
    GIT_AUTHOR_EMAIL="[email protected]" \ 
    GIT_AUTHOR_DATE="1146319620 -0400" \ 
    git commit-tree c658aa1ebcf2bf2a607696c7868b875be72fb01f \ 
     -p 4e671bf1d2298729c9e5cfd8229051cfe2c40831 

Questo ha creato un nuovo commit e ha stampato il suo hash (cc32e66 ...).Ora trasformarlo in un nuovo ramo:

git checkout -b fixed_commit cc32e66 

e rebase master sulla nuova filiale:

git checkout master 
git rebase fixed_commit 

E abbiamo finito:

Finished

Probabilmente da eliminare i vecchi rami e re-tag i commit appropriati.


In realtà potrebbe essere più semplice da utilizzare git filter-branch --parent-filter. Non l'ho provato

1

Si potrebbe provare uno rebase. C'è un esempio un po 'in basso (cerca --onto) che penso sia simile al tuo caso.

Io penso devi fare

git rebase --onto 1.02-1 1.02-3 

che dovrebbe mettere tutto dopo 1,02-3 su 1,02-1 e questo è probabilmente quello che volete.

Ricorda che gli hash saranno diversi su tutto dal primo commit modificato, ma presumo che tu stia facendo questo come primo passaggio nello spostamento da bzr, quindi nessun altro avrebbe dovuto clonarlo ancora.

+0

Questo sta dando un sacco di conflitti di fusione. Sembra che stia cercando di fare più del necessario. –

1

Ciò correggere i genitori senza cambiare niente altro (ad esempio le date committer.):

git filter-branch --tag-name-filter cat --parent-filter 'test $GIT_COMMIT = [sha of 1.02-6] && echo "-p [sha of 1.02-3]" || cat' -- 1.02-1..master

si dovrà sostituire il testo tra parentesi con l'appropriato impegnarsi ID. Se si dispone di più rami downstream che devono essere riscritti, modificare 1.02-1..master in --all ed essere pronti ad attendere.

Ovviamente, non utilizzare questa o altre soluzioni se altre sono derivate da qualsiasi commit dopo quelle che si desidera modificare. Ti odieranno.

+0

Se non è necessario preoccuparsi degli altri (ad esempio, nel caso di una pulizia subito dopo una conversione da svn o bzr a git e prima di essere trasferiti al server git), questa è la risposta migliore, davvero. Ho provato tutti loro. –

10

Il modo più semplice per fare questo (in git> = 1.6.5) è quello di utilizzare:

git replace --edit <sha> 

e rimuovere/aggiungere/modificare il Parent: linee.

Una volta soddisfatti del cambiamento è giusto, è possibile riscrivere il commit per rendere permanente la modifica:

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

Semplice e diretto al punto senza più comandi inclini agli errori. Questa dovrebbe essere la risposta accettata! –

+2

Nota possiamo eseguire il secondo comando come 'git filter-branch --tag-name-filter cat - ..head', quindi riscriviamo solo i commit necessari e non ogni singolo commit. Gli argomenti supportati sono documentati qui https://www.kernel.org/pub/software/scm/git/docs/git-rev-list.html – Michael

+0

Attenzione, in qualche modo questo crash sourcetree su mac in modo permanente – HopefullyHelpful

Problemi correlati