2014-05-05 18 views
5

Ho iniziato a scherzare con git filter-branch. L'opzione --all riscrive tutti i rami e i tag. Freddo. git filter-branch crea un backup di tutti i riferimenti che sovrascrive in refs/originale. Molto bello. Ora vorrei soffiare via tutti i miei esperimenti con filter-branch.annulla "git filter-branch ... - --all"? in un unico comando?

C'è un modo semplice per annullare completamente gli effetti di git filter-branch <whatever filter> -- --all? Cioè per ripristinare tutti i rami riscritti al loro stato originale tutto in una volta?

Se non esiste un modo preesistente, dovrebbe esserci. Se non esiste un modo preesistente, qualcuno ha uno script breve che lo farà?

Ovviamente ci sono soluzioni alternative. Potrei ripristinarlo manualmente, un ramo alla volta, come in this question. Oppure potrei solo nuotare e ripetere la clonazione. O diventerebbe noioso rapidamente in un repository con molti rami/tag che è (diciamo) divisi in repository più piccoli.

+0

Possibile duplicato di [Annulla git filter-branch] (https://stackoverflow.com/questions/14542326/undo-git-filter-branch) –

risposta

5

Ecco un modo semplice e sicuro per annullare un filtro-ramo:

git fetch . +refs/original/*:* 

Se il ramo attualmente estratto (HEAD) è uno dei rami da ristrutturare, questo comando non riuscirà. È possibile eseguire in anticipo git checkout --detach per consentire a git fetch di aggiornare tutti i rami. Ricordarsi di effettuare il checkout di una filiale dopo aver eseguito git fetch!

Una volta che gli arbitri sono stati ripristinati con successo, è possibile eliminare i refs/original arbitri in modo sicuro con questo comando:

git for-each-ref refs/original --format='delete %(refname) %(objectname)' | git update-ref --stdin 

Vecchia risposta:

git for-each-ref refs/heads refs/tags \ 
     --format='git update-ref "%(refname)" "%(refname)@{1 hour ago}"' 

Per una maggiore sicurezza si potrebbe verificare se il ramo filtro ha effettivamente aggiornato il riferimento:

+0

Sembra una buona soluzione per gli script (e l'analisi ha ampliato i miei orizzonti sed e git). L'uso di git update-ref dovrebbe renderlo più sicuro della copia manuale dei file (secondo i documenti git).Ha funzionato soprattutto quando l'ho provato, ma ho anche ricevuto alcuni errori come "fatale: Log per" ref/remotes/origin/master "ha solo 1 voci. Non sono ancora arrivato al fondo del perché. sh -x è anche un bel tocco, anche se l'output è confuso per qualche motivo. Sospetto che l'output dei sottoprocessi stia correndo verso l'uscita del terminale e si sia stampato l'uno sull'altro. – stochastic

+0

Sì, dovrebbe probabilmente renderlo 'git for-each-ref refs/heads refs/tags --format = etc.'. Fisso. – jthill

+0

Questo è, se git ha provato ad implementare un pulsante per ogni cosa a volte molto utile che puoi ottenere con poche righe di script, impiegherebbe più tempo per trovare il pulsante che fa ciò che vuoi piuttosto che implementarlo. – jthill

1

Ehmm, spostare tutti i riferimenti da .git/refs/original al loro posto in .git/refs/heads? Intendo letteralmente muovere, questi sono semplici file di testo. Puoi anche dare un'occhiata a .git/packed-refs se esiste.

+0

Grazie per questa risposta. Sapevo che quei file esistevano e che cosa facevano, ma fare confusione manualmente nella cartella .git sembrava corteggiare il disastro. Ho fatto questo: 'cd myrepo/.git/refs/original' ' cp -r refs/* ..' e quello sembrava fare il trucco. Quel file ref-packed mi preoccupa, però. So che i refset vengono usati come fallback se il file non esiste. Presumo che 'git filter-branch' non tocchi i ref-pack. Ci sono altri trucchi qui? – stochastic

+0

'packed-refs' viene creato durante' git gc' e usato come alternativa ai file di fatser in '.git/refs'. Solitamente, non è un problema dato che le voci in .git/refs lo sovrascrivono, e 'git filter-branch' è un'operazione abbastanza rara quindi non c'è bisogno di" automatizzare le cose ", ma solo per essere sicuri che tutto sia sotto il tuo controllo :) – user3159253