Dela via


Förstå förenklingen av Git-historiken

Azure DevOps Services | Azure DevOps Server | Azure DevOps Server 2022 | Azure DevOps Server 2020

Git-historikförenkling kan vara ett förvirrande odjur. 99% av tiden vet du inte ens om att det finns, men ibland hoppar det ut ur Gits mörka hörn och biter dig. I den här artikeln ska vi utforska vad historikförenkling är och hur det kan orsaka förvirring när du tittar på filhistorik.

Vi börjar med ett vanligt scenario:

  1. Du skickar en ändring till en fil och sammanfogar sedan ändringen i Main.
  2. Några av dina kollegor sammanfogar också sina grenar till main.
  3. Du kommer tillbaka en stund senare och märker att ändringarna saknas.
  4. Letar du efter den skyldige går du och tittar på filhistoriken och märker... dina ändringar visas inte ens!?

Git-incheckningshistorik är ett träd. Ibland är kronologisk historik inte samma som den faktiska filträdshistoriken. Den här situationen inträffar oftast när en sammanslagningscommit återställer en fil till sitt ursprungliga skick. I så fall visar standardhistorikvyn inte alla ändringar, eftersom filen tekniskt sett inte ändrades. I det här scenariot inser Git att det kan förenkla historiken och att de "ändringar" som du troligtvis letar efter tas bort från loggen.

Om du inte har stött på det förut, kan du bli frustrerad och undra Vart gick mina ändringar?

Historikförenkling: På som standard

Som standardinställning kommer körningen av loggkommandot på en fil: git log file.txt automatiskt att förenkla historiken, vilket möjligen döljer vissa kommandon från dess utdata. Mer information finns på sidan git log man.

Det som ökar förvirringen är att historikförenklingar inte inträffar om du bara kör git log, eftersom du tittar på alla ändringar finns det inget att förenkla.

För att inaktivera historikförenkling måste du använda kommandoradsväxeln --full-history.

Ett exempel på historikförenkling

För att bättre förstå hur förenkling fungerar skapar vi ett eget exempel på förenkling av historien. Först ska vi titta på ett diagram över den historik som vi ska skapa:

Git-grenar

Som du ser kommer vi att:

  1. Skapa en fil.
  2. Lägg till en rad i filen i en gren kallad "djur".
  3. Lägg till en annan rad i filen i en annan gren (frukt).
  4. Slå samman grenen djur tillbaka till huvudgrenen.
  5. Sammanfoga grenen frukt tillbaka till huvudgrenen och välj hela filkopian från fruktgrenen.
  6. Kontrollera filens historik.

Git kommer att förenkla historiken för oss. Steg 5 är nyckeln här. Vi ignorerade alla ändringar från grenen djur. Git kommer att märka att filen i stort sett inte ändrades mellan steg 1 och steg 5. Därför visas bara två historikposter.

Först skapar vi filen och lägger till den i vår lagringsplats:

> cd sample
> git init
> echo "some content" > test.txt
> git add test.txt
> git commit -m "Initial commit"

Nu bestämmer vi oss för att lägga till texten "åsnor" i filen under en djurkategori.

> git checkout -b animals
> echo "donkeys" >> test.txt
> git commit -am "We have added an animal"

Medan vi experimenterar bestämmer vi oss för att vi kanske vill gå med frukt i filen i stället, så vi skapar en annan gren och lägger till texten "bananas" i slutet av filen i stället:

> git checkout main -b fruit
> echo "bananas" >> test.txt
> git commit -am "We have added a fruit"

När vi känner oss nöjda med våra förändringar bestämmer vi oss för att slå samman vår djurgren till huvudgrenen:

> git checkout main
> git merge animals

Nu ska vi titta på loggen för vår test.txt-fil:

> git log test.txt
    
    commit 6b33d99b996c430a60c9552b79245d1aa8320339
        Date:   Mon Feb 15 10:45:33 2016 -0500

        We have added an animal

    commit 206613ccd9a54b055b184c7b6c16f2ece8067e51
        Date:   Mon Feb 15 10:44:18 2016 -0500

        Initial commit

Så långt så bra, eller hur? Ingenting ser ovanligt ut i våra loggutdata. Nu ska vi säga att vi ändrade oss och bestämde oss för att slå samman vår fruktgren:

>git merge fruit
    
    Auto-merging test.txt
    CONFLICT (content): Merge conflict in test.txt
    Automatic merge failed; fix conflicts and then commit the result.

Oj då, en sammanslagningskonflikt. Efter vissa överväganden bestämmer vi oss för att använda hela test.txt filen från vår fruktgren. Vanligtvis använder du någon form av textredigerare eller kopplingsverktyg, men vi återskapar bara hela filen eftersom det bara är två rader:

> echo "some content" > test.txt
> echo "bananas" >> test.txt
> git commit -am "Fixed merge conflict"

Nu ska vi ta en titt på historiken för vår test.txt-fil:

> git log test.txt
    
    commit fdd4dfd816c4efebc5bdb240f49e934e299db581
        Date:   Mon Feb 15 10:51:06 2016 -0500

        We have added a fruit

    commit 206613ccd9a54b055b184c7b6c16f2ece8067e51
        Date:   Mon Feb 15 10:44:18 2016 -0500

        Initial commit

Visst, vi ser inga ändringar från vårt första experiment i loggen, och vi ser inte heller vår sammanslagning! Är de kvar? Har Git helt eliminerat ändringarna?

> git log --full-history test.txt

Som du ser, även om det förenklade loggen utan flaggan full-history, har Git sparat alla våra ändringar:

> commit 5d0bb77a24e265dc154654fb3b5be331b53bf977
    Merge: 6b33d99 fdd4dfd
        Date:   Mon Feb 15 10:59:34 2016 -0500

        Fixed merge conflict

    commit fdd4dfd816c4efebc5bdb240f49e934e299db581
        Date:   Mon Feb 15 10:51:06 2016 -0500

        We have added a fruit

    commit 6b33d99b996c430a60c9552b79245d1aa8320339
        Date:   Mon Feb 15 10:45:33 2016 -0500

        We have added an animal

    commit 206613ccd9a54b055b184c7b6c16f2ece8067e51
        Date:   Mon Feb 15 10:44:18 2016 -0500

        Initial commit

Sammanfattning av git-historikförenkling

Saken med historieförenkling är att du för det mesta aldrig kommer att märka det. Men när en sammanslagningskonflikt går fel och du vill veta vad som hände kanske du tittar på git-logghistoriken och undrar vart dina ändringar har gått.

Istället för att få panik vet du att:

  • Historikförenkling för filer aktiveras som standard
  • Flaggan --full-history ger dig en mer omfattande filhistorik

Update: Sedan jag skrev den här artikeln har Azure DevOps Services introducerat ett antal fantastiska visningsalternativ för historik på webben. Det innebär att om du inte vill logga via kommandoraden kan du helt enkelt hämta filen som du vill visa historik för i utforskaren och du får nedanstående historikfilter där du kan ange enkla eller icke-enkla historikvyer:

Git-filter

(c) 2016 Microsoft Corporation. Alla rättigheter reserverade. Det här dokumentet tillhandahålls "i den mån det är". Information och vyer som uttrycks i det här dokumentet, inklusive URL och andra webbplatsreferenser, kan ändras utan föregående meddelande. Användande sker på egen risk.

Det här dokumentet ger dig inga juridiska rättigheter till någon immateriell rättighet i någon Microsoft-produkt. Du får kopiera och använda det här dokumentet som referens för interna syften.