Domanda

Ho sempre usato un client un'interfaccia basata git (SmartGit) e quindi non ho molta esperienza con la console git.

Tuttavia, ora di fronte alla necessità di sostituire una stringa in tutti i file .txt dalla storia (così, non cancellando l'intero file, ma solo sostituendo una stringa). Ho trovato il seguente comando:

git filter-branch --tree-filter 'git ls-files -z "*.php" |xargs -0 perl -p -i -e "s#(PASSWORD1|PASSWORD2|PASSWORD3)#xXxXxXxXxXx#g"' -- --all

Ho provato questo, e purtroppo notato che, mentre la password ha cambiarsi, tutti i file binari ha danneggiato. Immagini, ecc sarebbero tutti essere danneggiati.

C'è un modo migliore per fare questo che non danneggerà i miei file binari?

Grazie.

Modifica

Mi alzai mescolato con qualcosa. Il codice effettivo che i file binari causati da venga corrotta era:

$ git filter-branch --tree-filter "find . -type f -exec sed -i -e 's/originalpassword/newpassword/g' {} \;"

Il codice nella parte superiore in realtà rimosso tutti i file con la password stranamente.

È stato utile?

Soluzione

È possibile evitare i file indesiderati toccare passando -name "pattern" a find.

Questo funziona per me:

git filter-branch --tree-filter "find . -name '*.php' -exec sed -i -e \
    's/originalpassword/newpassword/g' {} \;"

Altri suggerimenti

Mi consiglia di utilizzare la BFG Repo-Cleaner , uno più semplice, più veloce alternativa al git-filter-branch specificamente progettato per la riscrittura dei file dalla storia Git.

Si dovrebbe seguire attentamente questi passaggi qui: https://rtyley.github.io/bfg-repo- pulitore / # utilizzo - ma la corona è proprio questo: di download del BFG vaso (richiede Java 7 o superiore) ed eseguire questo comando:

$ java -jar bfg.jar  --replace-text replacements.txt -fi *.php  my-repo.git

Il file replacements.txt dovrebbe contenere tutte le sostituzioni che si vuole fare, in un formato simile a questo (una voce per riga - nota i commenti non devono essere inclusi):

PASSWORD1 # Replace literal string 'PASSWORD1' with '***REMOVED***' (default)
PASSWORD2==>examplePass         # replace with 'examplePass' instead
PASSWORD3==>                    # replace with the empty string
regex:password=\w+==>password=  # Replace, using a regex
regex:\r(\n)==>$1               # Replace Windows newlines with Unix newlines

La vostra intera cronologia del repository verrà digitalizzato e file .php (sotto 1 MB di dimensione) avrà le sostituzioni effettuate: qualsiasi stringa di corrispondenza (che non è nel tuo ultima commit) sarà sostituito.

Full disclosure:. Sono l'autore del BFG Repo-Cleaner

Ho creato un file alla /usr/local/git/findsed.sh, con il seguente contenuto:

find . -name 'githubDirToSubmodule.sh' -exec sed -i '' -e 's/What I want to remove//g' {} \;

ho incontrato il comando:

git filter-branch --tree-filter "sh /usr/local/git/findsed.sh"

Descrizione dei comandi

Quando si esegue git filter-branch, questo passa attraverso ogni revisione che mai commesso, uno per uno. --tree filtro esegue lo script findsed.sh su ogni revisione impegnato, lo salva, poi progredisce alla prossima revisione.

Il comando find trova un file specifico o un insieme di file e esegue (-exec) l'editor sed su quel file. sed è un comando che richiede la regex dopo s / e lo sostituisce con la stringa tra / e / g (vuoto nel mio esempio). {} È un riferimento al percorso dei file che è stato dato dal comando find. Il percorso del file è alimentato a sed, in modo che sed sa su cosa lavorare. \; appena finisce il comando exec.

separa lo script di shell e comandi fuori in pezzi separati permette meno complicazioni quando si tratta di citazioni '' o "".

Peculiarità

I implementato con successo questo su un Mac, e apparentemente sed è un particolare (vecchio?) Versione su Mac. Questo è importante, come a volte si comporta in modo diverso. Assicurati di fare sed -i '' oppure è stata l'aggiunta di un "-e" alla fine del file, pensando che era quello che volevo per citarne i miei file di backup. -i '' dice file di backup di make non, basta modificare i file in atto e nessun file di backup necessari.

Come specificare -name 'filename.sh' mi ha aiutato a evitare un altro problema che non ho potuto risolvere. C'era un altro file con .sh e quel file è conclusa senza un carattere di nuova riga. sed per qualche motivo, sarebbe aggiungere un carattere di nuova riga alla fine, nonostante la 's / bla / bla / g' che non corrisponde nulla in quel file. Così, invece di capire che problema, ho appena detto che il ritrovamento di ignorare tutti gli altri file.

comandi addizionali che il lavoro

Inoltre, ho trovato questi comandi al lavoro nel file findsed.sh (un solo comando alla volta, non multple, così commento # gli altri fuori):

find . -name '.publishNewZenPackFromGithub.sh.swp' -exec rm -f {} \;
find . -name '*' -exec grep -H PassToRemove {} \;

Enjoy!

Potrebbe essere un problema di espansione shell. Se il filtro-ramo sta perdendo le virgolette intorno "*.php" nel momento in cui valuta il comando, può essere in espansione a nulla, quindi git ls-files -z elenco di tutti i file.

Si potrebbe verificare la fonte del filtro-ramo o cercando diversi trucchi quoting, ma quello che mi piacerebbe fare è solo fare uno script di shell di una riga che fa il vostro albero-filtro e passare che script invece.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top