Svenska â–Ÿ Topics â–Ÿ Latest version â–Ÿ git-filter-branch last updated in 2.44.0

NAMN

git-filter-branch - Skriv om grenar

SYNOPSIS

git filter-branch [--setup <kommando>] [--subdirectory-filter <katalog>]
	[--env-filter <kommando>] [--tree-filter <kommando>]
	[--index-filter <kommando>] [--parent-filter <kommando>]
	[--msg-filter <kommando>] [--commit-filter <kommando>]
	[--tag-name-filter <kommando>] [--prune-empty]
	[--original <namnrymd>] [-d <katalog>] [-f | --force]
	[--state-branch <gren>] [--] [<rev-list-alternativ>
​]

VARNING

git filter-branch har mÄnga fallgropar som kan ge svÄrupptÀckta fel i den avsedda historikomskrivningen (och lÀmnar ofta lite tid för felsökning eftersom prestandan Àr mycket dÄlig). SÀkerhets- och prestandaproblemen gÄr inte att ÄtgÀrda bakÄtkompatibelt, och dÀrför rekommenderas inte verktyget. AnvÀnd i stÀllet ett alternativt verktyg för historikfiltrering, till exempel git filter-repo. Om git filter-branch ÀndÄ mÄste anvÀndas, lÀs noggrant SAFETY (och PRESTANDA) för att förstÄ riskerna, och undvik sedan sÄ mÄnga av de listade farorna som möjligt.

BESKRIVNING

Gör det möjligt att skriva om Gits revisionshistorik genom att skriva om grenarna som nÀmns i <rev-list-options> och tillÀmpa anpassade filter pÄ varje revision. Filtren kan modifiera varje trÀd (t.ex. ta bort en fil eller köra en perl-omskrivning pÄ alla filer) eller information om varje incheckning. Annars bevaras all information (inklusive ursprungliga incheckningstider och sammanslagningsinformation).

Kommandot skriver bara om de positiva referenser som nÀmns pÄ kommandoraden (t.ex. om a..b anges skrivs endast b om). Om inga filter anges kommer incheckningarna att checkas in igen utan nÄgra Àndringar, vilket normalt inte skulle ha nÄgon effekt. Detta kan ÀndÄ vara anvÀndbart i framtiden för att kompensera för vissa Git-programfel eller liknande, dÀrför Àr sÄdan anvÀndning tillÄten.

OBS: Kommandot respekterar filen .git/info/grafts och referenser i namnrymden refs/replace/. Om grafts eller ersÀttningsreferenser Àr definierade kommer körning av detta kommando att göra dem permanenta.

VARNING! Den omskrivna historiken kommer att ha olika objektnamn för alla objekt och kommer inte att konvergera med den ursprungliga grenen. Den omskrivna grenen kan inte enkelt pushas och distribueras ovanpĂ„ den ursprungliga grenen. Kommandot bör inte anvĂ€ndas om de fullstĂ€ndiga konsekvenserna inte Ă€r kĂ€nda, och det bör undvikas Ă€ndĂ„ om en enkel incheckning skulle rĂ€cka för att lösa problemet. (Se avsnittet "ÅTERSTÄLLA FRÅN UPSTRÖMS-OMBASERING" i git-rebase[1] för mer information om att skriva om publicerad historik.)

Kontrollera alltid att den omskrivna versionen Àr korrekt: De ursprungliga referenserna, om de skiljer sig frÄn de omskrivna, kommer att lagras i namnrymden refs/original/.

Observera att eftersom den hÀr operationen Àr mycket I/O-intensiv, kan det vara en bra idé att omdirigera den temporÀra katalogen utanför-disken med alternativet -d, t.ex. pÄ tmpfs. Hastighetsökningen ska enligt uppgift vara mycket mÀrkbar.

Filter

Filtren tillÀmpas i den ordning som anges nedan. Argumentet <kommando> utvÀrderas alltid i shell-kontexten med hjÀlp av kommandot eval (med det anmÀrkningsvÀrda undantaget för incheckningsfiltret, av tekniska skÀl). Innan dess kommer miljövariabeln $GIT_COMMIT att stÀllas in för att innehÄlla ID:t för den incheckning som skrivs om. Dessutom tas GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, GIT_AUTHOR_DATE, GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL och GIT_COMMITTER_DATE frÄn den aktuella incheckningen och exporteras till miljön för att pÄverka författar- och incheckare-identiteterna för den ersÀttningsincheckning som skapats av git-commit-tree[1] efter att filtren har körts.

Om nÄgon utvÀrdering av <kommando> returnerar en avslutningsstatus som inte Àr noll, kommer hela operationen att avbrytas.

En map-funktion Àr tillgÀnglig som tar argumentet "original sha1 id" och matar ut ett "rewritten sha1 id" om incheckningen redan har skrivits om, och annars "original sha1 id". map-funktionen kan returnera flera id:n pÄ separata rader om ditt inchecknings-filter genererade flera incheckningar.

ALTERNATIV

--setup <kommando>

Det Àr inte ett riktigt filter som körs för varje incheckning utan en engÄngsinstÀllning precis före loopen. DÀrför Àr inga incheckningsspecifika variabler definierade Ànnu. Funktioner eller variabler som definieras hÀr kan anvÀndas eller modifieras i följande filtersteg förutom incheckningsfiltret, av tekniska skÀl.

--subdirectory-filter <katalog>

Only look at the history which touches the given subdirectory. The result will contain that directory (and only that) as its project root. Implies Ommappa till förfader.

--env-filter <kommando>

Filtret kan anvÀndas om bara miljön dÀr incheckningen ska utföras behöver Àndras. Mer specifikt kan det vara aktuellt att skriva om miljövariablerna för författare/incheckare-namn/e-postadress/tid (se git-commit-tree[1] för mer information).

--tree-filter <kommando>

Det Ă€r filtret för att skriva om trĂ€det och dess innehĂ„ll. Argumentet utvĂ€rderas i skal med arbetskatalogen satt till roten av det utcheckade trĂ€det. Det nya trĂ€det anvĂ€nds sedan som det Ă€r (nya filer lĂ€ggs till automatiskt, försvunna filer tas bort automatiskt - varken .gitignore-filer eller nĂ„gra andra ignoreringsregler HAR NÅGON EFFEKT!).

--index-filter <kommando>

Det Àr filtret för att skriva om indexet. Det liknar trÀdfiltret men kontrollerar inte trÀdet, vilket gör det mycket snabbare. AnvÀnds ofta med git rm --cached --ignore-unmatch ..., se EXEMPEL nedan. För svÄra fall, se git-update-index[1].

--parent-filter <kommando>

Det Ă€r filtret för att skriva om incheckningens förĂ€ldralista. Den kommer att ta emot förĂ€ldrastrĂ€ngen pĂ„ stdin och ska mata ut den nya förĂ€ldrastrĂ€ngen pĂ„ stdout. FörĂ€ldrastrĂ€ngen har formatet som beskrivs i git-commit-tree[1]: tom för den initiala incheckningen, "-p parent" för en normal incheckning och "-p parent1 -p parent2 -p parent3 
​" för en sammanslagningsincheckning.

--msg-filter <kommando>

Det Àr filtret för att skriva om incheckningsmeddelandena. Argumentet utvÀrderas i skalet med det ursprungliga incheckningsmeddelandet som standardindata; dess standardutdata anvÀnds som det nya incheckningsmeddelandet.

--commit-filter <kommando>

Det Ă€r filtret för att utföra incheckningen. Om detta filter anges kommer det att anropas i stĂ€llet för kommandot git commit-tree, med argument av formen "<TREE_ID> [(-p <PARENT_COMMIT_ID>)
​]" och loggmeddelandet pĂ„ stdin. Incheckning-ID förvĂ€ntas pĂ„ stdout.

Som ett speciellt tillÀgg, kan incheckningsfiltret generera flera inchecknings-id:n; i sÄ fall kommer de omskrivna under-ID:na till den ursprungliga incheckningen att ha alla som förÀldrar.

Du kan anvÀnda bekvÀmlighetsfunktionen map i det hÀr filtret, och Àven andra bekvÀmlighetsfunktioner. Om du till exempel anropar skip_commit "$@" kommer den aktuella incheckningen att utelÀmnas (men inte dess Àndringar! Om du vill ha det, anvÀnd git rebase i stÀllet).

Du kan ocksÄ anvÀnda git_commit_non_empty_tree "$@" i stÀllet för git commit-tree "$@" om du inte vill behÄlla incheckningar hos en enda förÀlder och det inte gör nÄgon Àndring av trÀdet.

--tag-name-filter <kommando>

Det Àr filtret för att skriva om taggnamn. NÀr det skickas kommer det att anropas för varje taggreferens som pekar pÄ ett omskrivet objekt (eller pÄ ett taggobjekt som pekar pÄ ett omskrivet objekt). Det ursprungliga taggnamnet skickas via standardindata, och det nya taggnamnet förvÀntas pÄ standardutdata.

De ursprungliga taggarna tas inte bort, men kan skrivas över; anvÀnd "--tag-name-filter cat" för att helt enkelt uppdatera taggarna. Var i det hÀr fallet mycket försiktig och se till att du har sÀkerhetskopierat de gamla taggarna ifall konverteringen skulle misslyckas.

NÀstan korrekt omskrivning av taggobjekt stöds. Om taggen har ett bifogat meddelande skapas ett nytt taggobjekt med samma meddelande, författare och tidsstÀmpel. Om taggen har en signatur bifogad, tas signaturen bort. Det Àr per definition omöjligt att bevara signaturer. Anledningen till att detta Àr "nÀstan" korrekt, Àr att om taggen helst inte Àndras (pekar pÄ samma objekt, har samma namn, etc.) borde den behÄlla eventuella signaturer. SÄ Àr inte fallet, signaturer kommer alltid att tas bort, anvÀndning pÄ egen risk. Det finns inte heller stöd för att Àndra författare eller tidsstÀmpel (eller taggmeddelandet för den delen). Taggar som pekar pÄ andra taggar kommer att skrivas om för att peka pÄ den underliggande incheckning.

--prune-empty

Vissa filter genererar tomma incheckningar som lÀmnar trÀdet orört. Flaggan instruerar git-filter-branch att ta bort sÄdana incheckningar om de har exakt en eller noll icke-beskÀrda förÀldrar; sammanslagningsincheckningar kommer dÀrför att förbli intakta. Flaggan kan inte anvÀndas tillsammans med --commit-filter, Àven om samma effekt kan uppnÄs genom att anvÀnda den angivna funktionen git_commit_non_empty_tree i ett incheckningsfilter.

--original <namn-utrymme>

AnvÀnd det hÀr alternativet för att ange namnrymden dÀr de ursprungliga incheckningar ska lagras. StandardvÀrdet Àr refs/original.

-d <katalog>

AnvÀnd det hÀr alternativet för att ange sökvÀgen till den temporÀra katalogen som anvÀnds för omskrivning. NÀr ett trÀdfilter tillÀmpas mÄste kommandot tillfÀlligt checka ut trÀdet till nÄgon katalog, vilket kan ta upp avsevÀrt utrymme vid stora projekt. Som standard görs detta i katalogen .git-rewrite/, men du kan ÄsidosÀtta det valet med den hÀr parametern.

-f
--force

git filter-branch vÀgrar att starta med en befintlig temporÀr katalog eller nÀr det redan finns referenser som börjar med refs/original/, om inte tvingad.

--state-branch <gren>

Det hÀr alternativet gör att mappningen frÄn gamla till nya objekt laddas frÄn den namngivna grenen vid start och sparas som en ny incheckning till den grenen vid avslutning, vilket möjliggör stegvis administration av stora trÀd. Om <gren> inte finns kommer den att skapas.

<rev-list alternativ>
​

Arguments for git rev-list. All positive refs included by these options are rewritten. You may also specify options such as --all, but you must use -- to separate them from the git filter-branch options. Implies Ommappa till förfader.

Ommappa till förfader

Genom att anvÀnda argument i git-rev-list[1], t.ex. sökvÀgsbegrÀnsare, kan du begrÀnsa mÀngden revisioner som skrivs om. Positiva referenser pÄ kommandoraden sÀrskiljs dock: vi lÄter dem inte exkluderas av sÄdana begrÀnsare. För detta ÀndamÄl skrivs de i stÀllet om för att peka pÄ den nÀrmaste förfadern som inte exkluderades.

UTGÅNGSSTATUS

Vid lyckat resultat, Àr avslutningsstatusen 0. Om filtret inte hittar nÄgra incheckningar att skriva om Àr avslutningsstatusen 2. Vid alla andra fel kan avslutningsstatusen vara vilket annat vÀrde som helst som inte Àr noll.

EXEMPEL

Anta att du vill ta bort en fil (som innehÄller konfidentiell information eller upphovsrÀttsintrÄng) frÄn alla incheckningar:

git filter-branch --tree-filter 'rm filename' HEAD

DÀremot, om filen saknas i trÀdet för nÄgon incheckning, kommer ett enkelt rm filename att misslyckas för det trÀdet och incheckningen. DÀrför kan du i stÀllet vilja anvÀnda rm -f filename som skript.

Att anvÀnda --index-filter med git rm ger en betydligt snabbare version. Precis som med rm filename kommer git rm --cached filename att misslyckas om filen saknas i trÀdet för en incheckning. Om du vill "glömma bort" en fil helt spelar det ingen roll nÀr den gick in i historiken, sÄ vi lÀgger ocksÄ till --ignore-unmatch:

git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD

Nu, fÄr du den omskrivna historiken sparad i HEAD.

För att skriva om kodförrÄdet sÄ att det ser ut som om foodir/ hade varit dess projektrot och ta bort all annan historik:

git filter-branch --subdirectory-filter foodir -- --all

SÄledes kan du t.ex. göra om en biblioteksunderkatalog till ett eget kodförrÄd. Observera -- som separerar filter-branch-alternativ frÄn revisionsalternativ, och --all för att skriva om alla grenar och taggar.

För att stÀlla in en incheckning (som vanligtvis ligger i början av en annan historik) som förÀlder till den aktuella initiala incheckningen, för att klistra in den andra historiken bakom den aktuella historiken:

git filter-branch --parent-filter 'sed "s/^\$/-p <graft-id>/"' HEAD

(om förĂ€lderstrĂ€ngen Ă€r tom – vilket hĂ€nder nĂ€r vi har att göra med den initiala incheckningen – lĂ€gg till graftincheckning som förĂ€lder). Observera att detta förutsĂ€tter historik med en enda rot (det vill sĂ€ga att ingen sammanslagning utan gemensamma förfĂ€der har skett). Om sĂ„ inte Ă€r fallet, anvĂ€nd:

git filter-branch --parent-filter \
	'test $GIT_COMMIT = <commit-id> && echo "-p <graft-id>" || cat' HEAD

eller Ànnu enklare:

git replace --graft $commit-id $graft-id
git filter-branch $graft-id..HEAD

För att ta bort incheckningar skrivna av "Darl McBride" frÄn historiken:

git filter-branch --commit-filter '
	if [ "$GIT_AUTHOR_NAME" = "Darl McBribe" ];
	then
		skip_commit "$@";
	else
		git commit-tree "$@";
	fi' HEAD

Funktionen skip_commit definieras enligt följande:

skip_commit()
{
	shift;
	while [ -n "$1" ];
	do
		shift;
		map "$1";
		shift;
	done;
}

Shift-magin kastar först bort trÀd-idn och sedan -p parametrarna. Observera att detta hanterar sammanslagningar korrekt! Om Darl genomförde en sammanslagning mellan P1 och P2 kommer den att propageras korrekt och alla underordnade attribut till sammanslagningen blir sammanslagningsincheckningar med P1 och P2 som sina förÀldrar i stÀllet för med sammanslagningsincheckningen som förÀlder.

OBS Àndringarna som introduceras av incheckningar, och som inte ÄterstÀlls av efterföljande incheckningar, kommer fortfarande att finnas i den omskrivna grenen. Om förÀndringar ocksÄ ska slÀngas tillsammans med incheckningar, bör det interaktiva lÀget i git rebase anvÀndas.

Incheckningsloggmeddelandena kan skrivas om med hjÀlp av --msg-filter. Till exempel kan git svn-id-strÀngar i ett kodförrÄd skapat av git svn tas bort pÄ följande sÀtt:

git filter-branch --msg-filter '
	sed -e "/^git-svn-id:/d"
'

Om Acked-by-rader behöver lÀggas till i, sÀg, de sista 10 incheckningarna (av vilka ingen Àr en sammanslagning), anvÀnd kommandot:

git filter-branch --msg-filter '
	cat &&
	echo "Acked-by: Bugs Bunny <bunny@bugzilla.org>"
' HEAD~10..HEAD

Alternativet --env-filter kan anvÀndas för att Àndra incheckare- och/eller författaridentitet. Om du till exempel upptÀcker att dina incheckningar har fel identitet pÄ grund av en felkonfigurerad user.email, kan du göra en korrigering innan du publicerar projektet, sÄ hÀr:

git filter-branch --env-filter '
	if test "$GIT_AUTHOR_EMAIL" = "root@localhost"
	then
		GIT_AUTHOR_EMAIL=john@example.com
	fi
	if test "$GIT_COMMITTER_EMAIL" = "root@localhost"
	then
		GIT_COMMITTER_EMAIL=john@example.com
	fi
' -- --all

För att begrÀnsa omskrivningen till endast en del av historiken, ange ett revisionsintervall utöver det nya grennamnet. Det nya grennamnet kommer att peka pÄ den översta revisionen som en git rev-list för detta intervall kommer att skriva ut.

Beakta pÄ denna historia:

     D--E--F--G--H
    /     /
A--B-----C

För att bara skriva om incheckningar D, E, F, G, H, men lÀmna A, B och C oberörda, anvÀnd:

git filter-branch ... C..H

För att skriva om incheckningar E, F, G, H, anvÀnd en av dessa:

git filter-branch ... C..H --not D
git filter-branch ... D..H --not C

För att flytta hela trÀdet till en underkatalog, eller ta bort det dÀrifrÄn:

git filter-branch --index-filter \
	'git ls-files -s | sed "s-\t\"*-&newsubdir/-" |
		GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
			git update-index --index-info &&
	 mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD

CHECKLISTA FÖR ATT KRYMPA ETT KODFÖRRÅD

git-filter-branch kan anvÀndas för att bli av med en delmÀngd av filer, vanligtvis med nÄgon kombination av --index-filter och --subdirectory-filter. Folk förvÀntar sig att det resulterande kodförrÄdet ska vara mindre Àn originalet, men du behöver nÄgra fler steg för att faktiskt göra det mindre, eftersom Git försöker hÄrt att inte förlora dina objekt förrÀn du sÀger Ät det att göra det. Se först till att:

  • Du tog verkligen bort alla varianter av ett filnamn om en blob flyttades under sin livstid. git log --name-only --follow --all -- filename kan hjĂ€lpa dig att hitta namnbyten.

  • Du filtrerade verkligen alla referenser: anvĂ€nd --tag-name-filter cat -- --all nĂ€r du anropar git-filter-branch.

Sedan finns det tvÄ sÀtt att fÄ ett mindre kodförrÄd. Ett sÀkrare sÀtt Àr att klona, vilket behÄller originalet intakt.

  • Klona den med git clone file:///sökvĂ€g/till/kodförrĂ„d. Klonen kommer inte att ha de borttagna objekten. Se git-clone[1]. (Observera att kloning med en vanlig sökvĂ€g bara hĂ„rdlĂ€nkar allt!)

Om du verkligen inte vill klona den, oavsett anledning, kontrollera följande punkter i stÀllet (i denna ordning). Detta Àr en mycket destruktiv metod, sÄ gör en sÀkerhetskopia eller ÄtergÄ till att klona den. Du har blivit varnad.

  • Ta bort de ursprungliga referenserna som sĂ€kerhetskopieras av git-filter-branch: sĂ€g git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d.

  • LĂ„t alla referensloggar upphöra med git reflog expire --expire=now --all.

  • SkrĂ€psamla alla orefererade objekt med git gc --prune=now (eller om din git-gc inte Ă€r tillrĂ€ckligt ny för att stödja argument till --prune, anvĂ€nd git repack -ad; git prune i stĂ€llet).

PRESTANDA

Prestandan för git-filter-branch Àr glacialt lÄngsam; dess design gör det omöjligt för en bakÄtkompatibel implementering att nÄgonsin vara snabb:

  • Vid redigering av filer kontrollerar git-filter-branch avsiktligt varje incheckning som den fanns i det ursprungliga kodförrĂ„det. Om ett kodförrĂ„d har 10^5 filer och 10^5 incheckningar, men varje incheckning bara modifierar fem filer, kommer git-filter-branch att krĂ€va 10^10 modifieringar, trots att det bara finns (högst) 5*10^5 unika blobbar.

  • Om du försöker fuska och försöker fĂ„ git-filter-branch att bara fungera pĂ„ filer som modifierats i en incheckning, sĂ„ hĂ€nder tvĂ„ saker

    • problem uppstĂ„r med borttagningar nĂ€r anvĂ€ndaren helt enkelt försöker byta namn pĂ„ filer (eftersom det verkar vara en icke-operation att försöka ta bort filer som inte finns; det krĂ€vs en del trick för att mappa om borttagningar över filnamn nĂ€r omdöpningarna sker via godtyckliga anvĂ€ndardefinierade skal)

    • Ă€ven om du lyckas med map-deletes-for-renames-chikanen, bryter du fortfarande tekniskt sett mot bakĂ„tkompatibilitet eftersom anvĂ€ndare tillĂ„ts filtrera filer pĂ„ sĂ€tt som beror pĂ„ incheckningarnas topologi i stĂ€llet för att filtrera enbart baserat pĂ„ filinnehĂ„ll eller namn (Ă€ven om detta inte har observerats i verkligheten).

  • Även om det inte finns behov av att redigera filer utan bara att t.ex. byta namn pĂ„ eller ta bort nĂ„gra och dĂ€rmed undvika att checka ut varje fil (dvs. --index-filter kan anvĂ€ndas), skickas fortfarande skalkodsnuttar för filtren. Det betyder att det för varje incheckning mĂ„ste finnas ett förberett Git-kodförrĂ„d dĂ€r filtren kan köras. Det Ă€r en omfattande förberedelse.

  • Dessutom, skapas eller uppdateras flera ytterligare filer per incheckning av git-filter-branch. NĂ„gra av dessa Ă€r till för att stödja de bekvĂ€mlighetsfunktioner som tillhandahĂ„lls av git-filter-branch (som map()), medan andra Ă€r till för att hĂ„lla reda pĂ„ internt tillstĂ„nd (men kunde ocksĂ„ ha nĂ„ts av anvĂ€ndarfilter; ett av git-filter-branchs regressionstester gör det). Detta innebĂ€r i huvudsak att man anvĂ€nder filsystemet som en IPC-mekanism mellan git-filter-branch och de anvĂ€ndardefinierade filtren. Diskar tenderar att vara en lĂ„ngsam IPC-mekanism, och att skriva dessa filer representerar ocksĂ„ effektivt en pĂ„tvingad synkroniseringspunkt mellan separata processer som vi trĂ€ffar vid varje incheckning.

  • De anvĂ€ndardefinierade skal-kommandona kommer sannolikt att involvera en pipeline av kommandon, vilket resulterar i att mĂ„nga processer per incheckning skapas. Att skapa och köra en annan process tar en mycket varierande tid mellan operativsystem, men pĂ„ alla plattformar Ă€r det mycket lĂ„ngsamt i förhĂ„llande till att anropa en funktion.

  • SjĂ€lva git-filter-branch Ă€r skrivet i skal (sh), vilket Ă€r ganska lĂ„ngsamt. Detta Ă€r det enda prestandaproblemet som skulle kunna Ă„tgĂ€rdas bakĂ„tkompatibelt, men jĂ€mfört med ovanstĂ„ende problem som Ă€r inneboende i designen av git-filter-branch, Ă€r sjĂ€lva verktygets sprĂ„k ett relativt litet problem.

    • Sidoanteckning: TyvĂ€rr tenderar folk att fixera sig vid det som Ă€r skrivet i skalet och frĂ„gar regelbundet om git-filter-branch kan skrivas om till ett annat sprĂ„k för att Ă„tgĂ€rda prestandaproblemen. Det ignorerar inte bara de större inneboende problemen med designen, det skulle ocksĂ„ hjĂ€lpa mindre Ă€n man skulle kunna förvĂ€nta sig: om git-filter-branch i sig inte vore skal, skulle bekvĂ€mlighetsfunktionerna (map(), skip_commit(), etc.) och argumentet --setup inte lĂ€ngre kunna köras en gĂ„ng i början av programmet utan skulle i stĂ€llet behöva lĂ€ggas till i varje anvĂ€ndarfilter (och dĂ€rmed köras om med varje incheckning).

Verktyget git filter-repo Àr ett alternativ till git-filter-branch som inte har sÄdana prestanda- eller sÀkerhetsproblem (se nedan). För den som redan har verktygskedjor som bygger pÄ git-filter-branch erbjuder git filter-repo Àven filter-lamely, en drop-in-ersÀttning för git-filter-branch (med vissa förbehÄll). filter-lamely har samma sÀkerhetsproblem som git-filter-branch, men förbÀttrar Ätminstone prestandan nÄgot.

SAFETY

git-filter-branch Àr full av missöden, vilket resulterar i olika sÀtt att enkelt korrumpera kodförrÄd eller sluta med en röra som Àr vÀrre Àn vad du började med:

  • NĂ„gon kan ha en uppsĂ€ttning "fungerande och testade filter" som de dokumenterar eller tillhandahĂ„ller till en kollega, som sedan kör dem pĂ„ ett annat operativsystem dĂ€r samma kommandon inte fungerar/testas (nĂ„gra exempel pĂ„ git-filter-branch manualsidan pĂ„verkas ocksĂ„ av detta). Skillnader mellan BSD och GNU-anvĂ€ndarland kan verkligen bita. Med tur dyker felmeddelanden upp. Men lika troligt Ă€r det att kommandona antingen inte utför den filtrering som begĂ€rs, eller sĂ„ korrumperar de tyst genom att göra nĂ„gon oönskad Ă€ndring. Den oönskade Ă€ndringen kan bara pĂ„verka ett fĂ„tal incheckningar, sĂ„ det Ă€r inte nödvĂ€ndigtvis uppenbart heller. (Det faktum att problem inte nödvĂ€ndigtvis Ă€r uppenbara innebĂ€r att de sannolikt kommer att gĂ„ obemĂ€rkta förbi förrĂ€n den omskrivna historiken har anvĂ€nts ett bra tag, och dĂ„ Ă€r det verkligen svĂ„rt att rĂ€ttfĂ€rdiga ytterligare en flaggdag för ytterligare en omskrivning.)

  • Filnamn med mellanslag hanteras ofta fel av shell-kodavsnitt eftersom de orsakar problem för shell-pipelines. Inte alla Ă€r bekanta med find -print0, xargs -0, git-ls-files -z, etc. Även personer som Ă€r bekanta med dem kan anta att sĂ„dana flaggor inte Ă€r relevanta eftersom nĂ„gon annan döpte om sĂ„dana filer i sitt kodförrĂ„d innan personen som utförde filtreringen gick med i projektet. Och ofta kanske inte ens de som Ă€r bekanta med att hantera argument med mellanslag gör det bara för att de inte Ă€r i tankesĂ€ttet att tĂ€nka pĂ„ allt som kan gĂ„ fel.

  • Filnamn som inte Ă€r ascii kan tas bort i tysthet trots att de finns i en önskad katalog. Att bara behĂ„lla önskade sökvĂ€gar görs ofta med hjĂ€lp av pipelines som git ls-files | grep -v ^WANTED_DIR/ | xargs git rm. ls-files citerar bara filnamn om det behövs, sĂ„ folk kanske inte mĂ€rker att en av filerna inte matchade regex (Ă„tminstone inte förrĂ€n det Ă€r alldeles för sent). Ja, nĂ„gon som kĂ€nner till core.quotePath kan undvika detta (sĂ„vida de inte har andra specialtecken som \t, \n eller "), och personer som anvĂ€nder ls-files -z med nĂ„got annat Ă€n grep kan undvika detta, men det betyder inte att de kommer att göra det.

  • PĂ„ liknande sĂ€tt, nĂ€r man flyttar filer, kan man upptĂ€cka att filnamn med tecken som icke-ascii eller specialtecken hamnar i en annan katalog, en som innehĂ„ller ett dubbelt citattecken. (Detta Ă€r tekniskt sett samma problem som ovan med citattecken, men kanske ett intressant annorlunda sĂ€tt som det kan och har manifesterats som ett problem.)

  • Det Ă€r alldeles för lĂ€tt att av misstag blanda ihop gammal och ny historik. Det Ă€r fortfarande möjligt med vilket verktyg som helst, men git-filter-branch inbjuder nĂ€stan till det. Om man har tur Ă€r den enda nackdelen att anvĂ€ndarna blir frustrerade över att de inte vet hur de ska krympa sitt kodförrĂ„d och ta bort det gamla. Om de har otur slĂ„r de ihop gammal och ny historik och fĂ„r flera "kopior" av varje incheckning, av vilka vissa innehĂ„ller oönskade eller kĂ€nsliga filer och andra inte. Detta sker pĂ„ flera olika sĂ€tt:

    • standardinstĂ€llningen Ă€r att bara göra en partiell omskrivning av historiken (--all Ă€r inte standardinstĂ€llningen och fĂ„ exempel visar det)

    • det faktum att det inte finns nĂ„gon automatisk rengöring efter körning

    • det faktum att --tag-name-filter (nĂ€r det anvĂ€nds för att byta namn pĂ„ taggar) inte tar bort de gamla taggarna utan bara lĂ€gger till nya med det nya namnet

    • det faktum att vĂ€ldigt lite vĂ€gledande information ges för att hjĂ€lpa anvĂ€ndare att förstĂ„ följderna av en omskrivning och hur man undviker att blanda gammal och ny historik. Manualsidan beskriver till exempel att anvĂ€ndare behöver förstĂ„ att de mĂ„ste ombasera sina Ă€ndringar pĂ„ alla sina grenar ovanpĂ„ den nya historiken (eller ta bort och klona om), men det Ă€r bara en av flera aspekter att ta hĂ€nsyn till. Se avsnittet "DISCUSSION" i manualen för git filter-repo för mer detaljer.

  • Annoterade taggar kan av misstag konverteras till lĂ€ttviktstaggar pĂ„ grund av ett av tvĂ„ problem:

    • NĂ„gon kan skriva om historiken, inse att de har gjort fel, Ă„terstĂ€lla frĂ„n sĂ€kerhetskopiorna i refs/original/ och sedan göra om sitt git-filter-branch-kommando. (SĂ€kerhetskopieringen i refs/original/ Ă€r inte en riktig sĂ€kerhetskopia; den avreferenserar taggar först.)

    • Kör git-filter-branch med antingen --tags eller --all i din <rev-list-alternativ>. För att behĂ„lla kommenterade taggar som kommenterade mĂ„ste du anvĂ€nda --tag-name-filter (och fĂ„r inte ha Ă„terstĂ€llt frĂ„n refs/original/ i en tidigare misslyckad omskrivning).

  • Alla incheckningsmeddelanden som anger en kodning kommer att bli korrupta av omskrivningen; git-filter-branch ignorerar kodningen, tar de ursprungliga bytena och matar den till commit-tree utan att ange rĂ€tt kodning. (Detta hĂ€nder oavsett om --msg-filter anvĂ€nds eller inte.)

  • Incheckningsmeddelanden (Ă€ven om de alla Ă€r i UTF-8) blir som standard korrupta pĂ„ grund av att de inte uppdateras — alla referenser till andra incheckningshashar i incheckningsmeddelanden kommer nu att referera till incheckningar som inte lĂ€ngre finns.

  • Det finns inga funktioner som hjĂ€lper anvĂ€ndare att hitta vilket oönskat skrĂ€p de ska ta bort, vilket innebĂ€r att de Ă€r mycket mer benĂ€gna att ha ofullstĂ€ndiga eller partiella rensningar som ibland leder till förvirring och att folk slösar tid pĂ„ att försöka förstĂ„. (Till exempel tenderar folk att bara leta efter stora filer att ta bort i stĂ€llet för stora kataloger eller tillĂ€gg, och nĂ€r de vĂ€l gör det, kommer personer som anvĂ€nder det nya kodförrĂ„det och gĂ„r igenom historiken nĂ„gon gĂ„ng senare att mĂ€rka en katalog för bygg-artefakter som innehĂ„ller vissa filer men inte andra, eller en cache av beroenden (node_modules eller liknande) som aldrig kunde ha fungerat eftersom den saknar vissa filer.)

  • Om --prune-empty inte anges kan filtreringsprocessen skapa massor av förvirrande tomma incheckningar

  • Om --prune-empty anges, sĂ„ beskĂ€rs Ă€ven avsiktligt placerade tomma incheckningar frĂ„n tiden före filtreringsĂ„tgĂ€rden, i stĂ€llet för att bara beskĂ€ra incheckningar som blev tomma pĂ„ grund av filtreringsregler.

  • Om --prune-empty anges, missas ibland tomma incheckningar och lĂ€mnas kvar Ă€ndĂ„ (ett nĂ„got ovanligt programfel, men det hĂ€nder
​)

  • Ett mindre problem, men anvĂ€ndare som har som mĂ„l att uppdatera alla namn och e-postadresser i ett förar kan ledas till --env-filter som bara uppdaterar författare och incheckare, och saknar taggare.

  • Om anvĂ€ndaren anger ett --tag-name-filter som mappar flera taggar till samma namn, visas ingen varning eller fel; git-filter-branch skriver helt enkelt över varje tagg i nĂ„gon odokumenterad fördefinierad ordning vilket resulterar i endast en tagg i slutet. (Ett regressionstest av git-filter-branch krĂ€ver detta överraskande beteende.)

Dessutom, leder den dÄliga prestandan hos git-filter-branch ofta till sÀkerhetsproblem:

  • Att komma pĂ„ rĂ€tt shell-kodsavsnitt för att utföra den filtrering man vill ha Ă€r ibland svĂ„rt om man inte bara gör en trivial modifiering, som att ta bort ett par filer. TyvĂ€rr lĂ€r sig folk ofta om kodavsnittet Ă€r rĂ€tt eller fel genom att prova sig fram, men om det Ă€r rĂ€tt eller fel kan variera beroende pĂ„ speciella omstĂ€ndigheter (mellanslag i filnamn, non-ascii filnamn, roliga författarnamn eller e-postadresser, ogiltiga tidszoner, förekomst av grafts eller ersĂ€ttningsobjekt, etc.), vilket innebĂ€r att de kan behöva vĂ€nta lĂ€nge, stöta pĂ„ ett fel och sedan starta om. Prestandan för git-filter-branch Ă€r sĂ„ dĂ„lig att denna cykel Ă€r smĂ€rtsam, vilket minskar tiden som finns tillgĂ€nglig för att noggrant kontrollera om (för att inte tala om vad det gör med tĂ„lamodet hos den person som gör omskrivningen Ă€ven om de tekniskt sett har mer tid tillgĂ€nglig). Detta problem förvĂ€rras ytterligare eftersom fel frĂ„n trasiga filter kanske inte visas pĂ„ lĂ€nge och/eller gĂ„r vilse i ett hav av utdata. Ännu vĂ€rre Ă€r att trasiga filter ofta bara resulterar i tysta felaktiga omskrivningar.

  • Som grĂ€dde pĂ„ moset, Ă€ven nĂ€r anvĂ€ndare Ă€ntligen hittar fungerande kommandon, vill de naturligtvis dela med sig av dem. Men de kanske inte Ă€r medvetna om att deras kodförrĂ„d inte hade vissa specialfall som nĂ„gon annans har. SĂ„ nĂ€r nĂ„gon annan med ett annat kodförrĂ„d kör samma kommandon, drabbas de av problemen ovan. Eller sĂ„ kör anvĂ€ndaren bara kommandon som egentligen granskades för specialfall, men de kör dem pĂ„ ett annat operativsystem dĂ€r det inte fungerar, som nĂ€mnts ovan.

GIT

En del av git[1]-sviten