Vooruitblik op Git 2.56 — en 3.0

Het broncodebeheersysteem Git vormt de kern van ontwikkelingsprocessen wereldwijd. Daarom zijn wijzigingen, en met name incompatibele wijzigingen, van groot belang voor de betrokken ontwikkelaars. De release van Git 2.56, die rond eind september wordt verwacht, is momenteel beschikbaar als release-candidate. Hoewel deze versie niet de meest baanbrekende is, kan de daaropvolgende release — mogelijk de langverwachte Git 3.0 — dat wel zijn.

Wat zit er in Git 2.56?

De release van Git 2.56 bevat ruim 700 non-merge commits. Het brengt een aantal mooie verbeteringen, maar zal de Git-ervaring voor de meeste gebruikers niet fundamenteel veranderen. Een functie die wel potentie biedt, is de toevoeging van het drop-subcommando aan de (nog experimentele) git history toolbox:

$ git history drop commit-id

Dit commando zorgt ervoor dat de geïdentificeerde commit wordt verwijderd uit de geschiedenis van de huidige branch, waarna alle commits die daarna zijn toegevoegd opnieuw worden afgespeeld. Dit biedt een eenvoudigere manier om een problematische commit te verwijderen. Helaas werkt dit nog niet als de geschiedenis merge-commits bevat, waardoor het onbruikbaar is voor veel (of de meeste) repositories.

Het git status-commando zal nu een git pull-commando suggereren om een branch bij te werken die achterloopt op de branch die het volgt. Het zal echter nog steeds aangeven dat een branch "up to date" is, zelfs als deze achterloopt op een (niet-gefetched) remote tracking branch.

Het git refs-commando is bedoeld voor het manipuleren van referenties op een laag niveau; in versie 2.56 heeft dit een aantal nieuwe subcommando's gekregen. Deze commando's — create, delete, update en rename — doen, wellicht verrassend voor Git, precies wat hun namen suggereren.

Daarnaast zijn er verschillende kleine verbeteringen in de gebruiksvriendelijkheid:

  • De nieuwe optie --delete-merged voor git branch verwijdert lokale branches die zijn samengevoegd met hun remote tracking branches.
  • Een poging om een branch te verwijderen met git branch -d zal mislukken, inclusief een nuttige melding, als die branch wordt gebruikt voor bisection.
  • Pogingen om het configuratiebestand te vergrendelen worden bij fouten opnieuw geprobeerd, wat irritatie voorkomt wanneer meerdere commando's tegelijkertijd het bestand proberen te wijzigen.
  • git add heeft een nieuwe optie --resolved die alleen bestanden toevoegt met merge-conflicten die zijn opgelost.

Verder is er de gebruikelijke lange lijst met bugfixes, refactorings en prestatieverbeteringen. Al met al ziet 2.56 eruit als een solide release, maar het vertoont ook tekenen van een project dat veel van het significantere werk bewaart voor de toekomst. Dat roept de vraag op wat er daarna komt.

Na 2.56?

Begin september vroeg Git-onderhouders Junio Hamano aan de community wat de volgende release zou moeten zijn. Zou het beste zijn om de 3.0-release uit te brengen waar de community al enige tijd naartoe werkt, om het jaar in stijl af te sluiten? Of is er eerst nog behoefte aan één of meerdere 2.x-releases voordat 3.0 kan plaatsvinden?

Dit is een belangrijke vraag, omdat 3.0 een aantal breuken in compatibiliteit zal bevatten die sommige gebruikers kunnen doen aarzelen voor een upgrade. De meest significante hiervan is waarschijnlijk de overstap naar de SHA-256 hashfunctie als standaard, in plaats van de SHA-1 hash die Git vanaf het begin heeft gebruikt. SHA-1 wordt al lang als zwak beschouwd, wat zorgwekkend is voor applicaties zoals Git. Hashes worden gebruikt om elk object (bestanden, directorybomen, commits) in de Git-repository te identificeren en om de keten van commits naar een bepaald punt te verifiëren. Als SHA-1 gekraakt kan worden, zou het theoretisch mogelijk zijn om de geschiedenis van een repository op manieren te wijzigen die moeilijk of onmogelijk te detecteren zijn.

Git heeft al lang verdedigingsmechanismen ingebouwd tegen bekende SHA-1-aanvallen, en weinigen lijken momenteel ernstig bezorgd over de kans op gecompromitteerde repositories. Toch is het zeer zinvol om over te stappen naar een veiligere hashfunctie.

Niet-experimentele ondersteuning voor SHA-256 is aanwezig in Git sinds release 2.42 in 2023, hoewel sommige koppelingen voor interoperabiliteit met oudere repositories langer in beslag hebben genomen. De grootste zorg die Git-ontwikkelaars heeft tegengehouden om standaard over te stappen op SHA-256, was de ondersteuning (of het gebrek daaraan) bij de grote forge-sites. GitLab heeft ondersteuning sinds 2024 en Forgejo ondersteunt het ook. De "olifant in de kamer" is echter GitHub; het uitbrengen van een versie van Git die repositories creëert die incompatibel zijn met GitHub is een zorgwekkend vooruitzicht.

Het is nog niet duidelijk wanneer GitHub deze ondersteuning toevoegt, maar het is opmerkelijk dat Brian M. Carlson, een GitHub-medewerker en een belangrijke ontwikkelaar achter de SHA-256-transitie, reageerde op de vraag van Hamano door te zeggen dat er nieuws over dit onderwerp aan komt en dat het maken van 3.0 als volgende release waarschijnlijk de beste keuze is.

Dat gezegd hebbende, heeft Carlson nog één andere wijziging voorgesteld die hij graag zou zien vóór de release van 3.0. Hoewel Git hexadecimale getallen (specifiek object-ID's) altijd als lowercase strings heeft beheerd, accepteert het ook uppercase ID's. Dit leidt tot situaties waarin twee schijnbaar verschillende ID's (bijvoorbeeld f00f00 en F00F00) feitelijk hetzelfde zijn. Hierdoor zijn bugs en beveiligingskwetsbaarheden ontstaan. Daarom wil Carlson het gedrag van Git wijzigen zodat alleen ID's in lowercase worden geaccepteerd. Dit is een wijziging die waarschijnlijk niet voor veel gebruikers problemen zal opleveren, maar er is vrijwel zeker iemand die op dit gedrag vertrouwt.

Een andere significante wijziging die wacht op de 3.0-release is de overstap naar het "reftable"-mechanisme. Een referentie (meestal "ref") in Git is een associatie tussen een naam en een object in de repository; branches, tags en remotes zijn bijvoorbeeld allemaal refs.

Git slaat momenteel (standaard) elke ref op als een bestand onder .git/refs/ in de repository. Als een repository een branch genaamd foo bevat, is er een bestand .git/refs/heads/foo dat het ID bevat van de commit aan het hoofd van die branch. Er is ook een mechanisme om al deze refs samen te voegen in een packed-refs-bestand, wat de prestaties verbetert — tot op zekere hoogte.

Dit mechanisme werkt, maar wordt steeds inefficiënter naarmate het aantal refs groeit. In sommige projecten groeit dit aantal inderdaad aanzienlijk. Volgens de documentatie over reftables bevat de Android-repository meer dan 800.000 refs. Op die schaal kan het opzoeken van refs, of het bepalen of er refs bestaan die naar een specifieke commit wijzen, een kostbare operatie zijn. Het vertragen van de ontwikkeling kan een "geelkaart-niveau" irritatie zijn, wat leidt tot de wens om iets aan de refs te doen.

De Git 2.45-release voegde reftables toe als een efficiëntere manier om refs op te slaan. Het is een binair bestand dat is geoptimaliseerd voor zowel ruimte-efficiëntie als snelle toegang. Sindsdien is het mogelijk om een repository te maken die een reftable gebruikt in plaats van het oude op bestanden gebaseerde mechanisme, maar dat is nooit de standaard geworden.

De overstap naar reftable zou voor gebruikers van Git zelf geen zichtbare gevolgen moeten hebben (behalve betere prestaties), maar het kan een probleem zijn voor gebruikers van andere softwarepakketten die toegang hebben tot Git-repositories. Carlson noemde in zijn e-mail libgit2 als een potentieel zorgpunt.

Zo blijkt dat libgit2 hier geen blokkade zal vormen; Patrick Steinhardt heeft laten weten dat hij reftable-ondersteuning aan libgit2 heeft toegevoegd en dat SHA-256-ondersteuning in augustus standaard is ingeschakeld. libgit2 zou dus klaar moeten zijn voor de transitie naar Git 3.0.

Ten slotte is er, zoals genoemd door Carlson, de kwestie van Rust. Het project heeft enkele proefondersteuningen toegevoegd voor code geschreven in Rust, maar heeft getwijfeld om Rust verplicht te maken voor het bouwen van Git. Ook dit zal naar verwachting veranderen in de 3.0-release; daarna zullen platforms zonder een werkende Rust-compiler niet in staat zijn om te upgraden.

Na deze punten op te sommen, suggereerde Carlson dat ze de 3.0-release waarschijnlijk niet zouden moeten tegenhouden:

"Ik denk dat iedereen die nu al niet extreem ver gevorderd is met SHA-256 (en reftable, voor software die met lokale repositories werkt) waarschijnlijk niet meegewogen hoeft te worden. JGit en Gitoxide zijn bijvoorbeeld al meer dan een jaar geleden geïnformeerd dat SHA-256 in Git 3.0 zou komen. (Ik weet dat, want ik heb hen geïnformeerd.) Evenzo ben ik me niet bewust van iemand die serieus Rust-ondersteuning onderneemt voor platforms die dat nog niet ondersteunen, dus ik denk niet dat dat een blokkade zou moeten zijn."

Dit leidde tot zijn conclusie dat het waarschijnlijk de beste keuze zou zijn om de volgende release aan te merken als 3.0.

Wat er daadwerkelijk zal gebeuren, is nog niet publiekelijk aangekondigd; dat hangt af van de beslissing van Hamano. Zoals hij het verwoordde: "dit is geen populariteitswedstrijd, noch is het een democratie". In de bijna twee weken sinds zijn vraag is er echter geen sterke oppositie geweest tegen het overstappen naar het 3.x-tijdperk en het achterlaten van sommige vroege ontwerpbeslissingen van Git (hoewel repositories die SHA-1 gebruiken en geen reftables hebben, natuurlijk volledig ondersteund zullen blijven worden). Als de 3.0-release niet in 2026 verschijnt, lijkt het zeker dat deze kort daarna zal volgen.