Repository navigation
Releases: 74nu5/sourcegit
Release list
2026.22-3b.1
Le fork passe sur SourceGit 2026.22.
Base : SourceGit 2026.22. Tout ce que le fork ajoute est repris à l'identique, sans
conflit.
Ce qu'apporte l'amont, entre autres : un graphique en camembert des principaux
contributeurs dans les statistiques, une icône quand une commande tourne en arrière-plan,
« Ouvrir dans l'explorateur » dans le menu d'un onglet de dépôt, et un surveillant de
fichiers qui ne manque plus les références rangées dans packed-refs.
Avec les worktrees regroupés sous leur dépôt, « Ouvrir dans l'explorateur » ouvre le
worktree affiché.
Une correction propre au fork, nécessaire avec cette version. L'amont inscrit
désormais dans l'AppImage l'adresse où chercher ses mises à jour, et publie les fichiers
.zsync que lisent les outils de mise à jour d'AppImage (AppImageUpdate, Gear Lever…).
Cette adresse désignait le dépôt de l'amont : compilée telle quelle, l'AppImage du fork
aurait invité ces outils à la remplacer par celle de l'amont, sans avertissement. Elle
désigne maintenant le dépôt qui la compile — ici, ce fork.
La release porte donc deux fichiers de plus, un .zsync par architecture. La mise à jour
intégrée du fork n'est pas concernée.
Le placement compact du graphe reste identique à l'octet près à celui de l'amont : cette
version de l'amont n'y touche pas.
Un programme qui sait se mettre à jour doit d'abord savoir d'où il vient.
2026.21-3b.5
Dans les modifications locales, l'arbre des fichiers se déplie et se replie d'un coup.
Base : SourceGit 2026.21, inchangée.
Demandé dans l'issue #7. Un arbre profond se repliait jusqu'ici dossier par dossier.
En mode arbre, un clic droit sur la liste des fichiers non indexés ou indexés propose
désormais « Déplier tous les dossiers » et « Replier tous les dossiers ». Le menu s'ouvre
même quand rien n'est sélectionné : il ne contient alors que ces deux entrées, l'amont
n'en ouvrant aucun dans ce cas. Chacune n'est active que si elle change quelque chose à
l'écran.
Replier tout replie aussi les dossiers imbriqués. Déplier tout garde la sélection, et
avec elle le diff affiché à côté.
Un défaut de l'amont est corrigé au passage, parce que « tout replier » l'aurait
rendu systématique : la liste retenait les dossiers repliés d'un rafraîchissement à
l'autre en lisant les seules lignes visibles. Un dossier replié à l'intérieur d'un
dossier lui-même replié était donc oublié au premier fichier enregistré, et revenait
déplié.
Les commandes sont dans le menu contextuel plutôt qu'en boutons : les en-têtes des deux
listes sont déjà pleins, et des boutons de plus y changeraient l'affichage pour tout le
monde.
Empreinte sur les fichiers de l'amont : huit lignes ajoutées, aucune supprimée.
Le placement compact du graphe reste identique à l'octet près à celui de l'amont.
Un arbre qu'on ne peut que déplier une branche à la fois finit toujours déplié.
2026.21-3b.4
Les réglages du fork ne sont plus effacés quand SourceGit amont est lancé sur la même
machine.
Base : SourceGit 2026.21, inchangée.
Le fork et l'amont partagent le même dossier de réglages. L'amont, en enregistrant,
réécrit preference.json en entier avec ses seuls champs : le lancer une seule fois
effaçait tous les réglages du fork — les options du graphe, les comptes de forge et
leurs jetons. De même, dans chaque dépôt, sourcegit.uistates perdait la branche épinglée,
les sections masquées de la barre latérale, les remises affichées dans le graphe et les
largeurs de colonnes.
Ces réglages vivent désormais dans des fichiers à eux, à côté de ceux de l'amont,
qui ne les ouvre jamais :
- preference.fork.json, dans le dossier des réglages, pour l'application ;
- sourcegit.fork.uistates, dans le dossier .git de chaque dépôt, pour le dépôt.
Rien à faire pour les récupérer. Au premier lancement, les réglages sont relus là où
les versions précédentes les rangeaient, avant tout enregistrement, puis déplacés dans
leurs nouveaux fichiers. Un dépôt les déplace la première fois qu'il est rouvert.
Un jeton saisi plutôt que lu dans une variable d'environnement reste stocké en clair,
désormais dans preference.fork.json.
Revenir ensuite à une version antérieure du fork fait perdre ses réglages dans cette
version : elle les cherche là où ils ne sont plus.
Empreinte sur les fichiers de l'amont : trois lignes dans les préférences, deux dans
l'état des dépôts — qui perd au passage les deux propriétés que le fork y avait
ajoutées.
Le placement compact du graphe reste identique à l'octet près à celui de l'amont.
Deux programmes qui partagent un dossier n'ont pas à partager un fichier.
2026.21-3b.3
Les worktrees d'un dépôt peuvent désormais vivre sous l'onglet de leur dépôt, en une
rangée de sous-onglets, au lieu d'occuper chacun un onglet en fin de barre.
Base : SourceGit 2026.21, inchangée.
Chaque worktree ouvert devenait jusqu'ici un onglet à part, nommé d'après son dossier,
sans lien avec son dépôt. Avec l'option, un dépôt garde un seul onglet, et ses worktrees
forment une rangée juste en dessous, chacun nommé d'après sa branche.
L'option s'active d'un clic droit sur un onglet : « Regrouper les worktrees sous
leur dépôt ». Elle s'applique immédiatement aux onglets déjà ouverts, et la désactiver
rend un onglet à chaque worktree. Désactivée par défaut ; la barre d'onglets est alors
exactement celle de l'amont, comme elle l'est aussi pour un dépôt sans worktree lié.
Ouvrir un worktree dont le dépôt a déjà son onglet le sélectionne dans la rangée. Ouvrir
un worktree dont le dépôt n'est pas ouvert ouvre l'onglet du dépôt, ce worktree affiché.
Au redémarrage, chaque groupe revient sur le worktree qui était affiché.
Un worktree n'est ouvert qu'à la première visite de son sous-onglet : un worktree
jamais regardé ne coûte ni surveillant de fichiers ni minuterie d'auto-fetch. Fermer
l'onglet ferme tous les worktrees qu'il a ouverts. Un worktree supprimé ferme son
sous-onglet — mais seulement une fois son dossier disparu, pour qu'une liste revenue vide
d'un échec ponctuel de git ne referme pas tout.
Seul le worktree affiché ouvre des fenêtres dans l'onglet. Les autres ne font pas
d'auto-fetch : ils partagent leurs remotes avec celui qui est affiché, un fetch les sert
tous. Et on ne change pas de sous-onglet pendant qu'une opération est en cours : elle
appartient au worktree qui l'a lancée.
Le point de modification de l'onglet reflète le worktree affiché, pas l'ensemble du
groupe.
Un dépôt retrouvait son onglet en comparant l'identité de l'onglet à son propre chemin.
Un worktree logé dans l'onglet de son dépôt n'en aurait trouvé aucun — et comme toutes
les actions demandent d'abord s'il peut ouvrir une fenêtre, fetch, pull, push et commit
n'auraient simplement rien fait. C'est corrigé, et vérifié sur de vrais dépôts : un
principal, un worktree sur une branche, un en HEAD détachée, un dépôt nu, et un
--separate-git-dir, dont les worktrees ne sont pas regroupés faute de pouvoir situer sa
copie de travail.
Empreinte sur les fichiers de l'amont : un mot, une ligne pour retrouver l'onglet, trois
points d'accroche dans le lanceur, la rangée dans l'onglet, une ligne dans le menu.
Aucune ligne supprimée.
Le placement compact du graphe reste identique à l'octet près à celui de l'amont.
Un worktree n'est pas un autre dépôt : c'est le même, ouvert ailleurs — il a sa place
sous son nom, pas au bout de la barre.
2026.21-3b.2
Une remise affichée dans le graphe a enfin le menu d'une remise, on peut retrouver
l'endroit où elle a été prise, et deux défauts de la barre d'onglets sont corrigés.
Base : SourceGit 2026.21, inchangée.
Le clic droit sur une remise dans le graphe proposait le menu d'un commit :
reset, rebase, cherry-pick, revert, rebase interactif. Toutes ces actions
s'exécutaient, sur ce que l'utilisateur tient pour du travail mis de côté. Une
remise reçoit maintenant les actions d'une remise — appliquer, créer une branche,
supprimer, enregistrer en patch, copier le message —, les mêmes que sur la page des
remises. Une sélection multiple qui en contient une n'a plus de menu du tout.
La remise est retrouvée par son empreinte au moment où le menu s'ouvre, et non
mémorisée sur la ligne. Git désigne les remises par leur position — stash@{1} — et
en supprimer une renumérote les suivantes : une ligne qui aurait gardé l'ancienne
aurait appliqué ou supprimé une autre remise que celle cliquée, sans aucun message.
Aller à l'endroit où elle a été prise. Le premier parent d'une remise est le
commit sur lequel le travail a été mis de côté. Les deux côtés — la page des remises
et le graphe — proposent désormais d'y aller, ainsi que le passage de l'un à
l'autre. L'entrée est désactivée, avec la raison, quand ce commit n'est pas dans
l'historique chargé : sinon le clic aurait eu l'air ignoré. L'option qui dessine les
remises dans le graphe n'est jamais activée à votre place.
Le message comme libellé, en option depuis le menu de la page des remises.
L'index ne disparaît pas : il descend en seconde ligne, parce que c'est lui que
nomment les boîtes de confirmation. Désactivé par défaut, et la page est alors
exactement celle de l'amont.
Un titre trop long est tronqué d'une ellipse au lieu d'être rogné des deux côtés.
L'onglet actif revient au redémarrage même si un dépôt a disparu. Un dépôt qui ne
s'ouvre plus était sauté, et tous les onglets suivants glissaient d'un rang : c'est
celui d'après qui revenait. L'onglet est désormais retrouvé par son chemin.
Empreinte sur les fichiers de l'amont : deux lignes pour les menus, dont une que
le fork possédait déjà, douze pour la page des remises, et huit pour la barre
d'onglets. Aucune ligne supprimée.
Le placement compact du graphe reste identique à l'octet près à celui de l'amont.
Une remise se désigne par sa place dans une pile qui bouge : on ne la retrouve de
façon sûre que par ce qu'elle contient.
2026.21-3b.1
L'épinglage d'une branche dans la colonne de gauche du graphe fonctionne
désormais en mode compact, et non plus seulement en mode « lanes stables ».
Base : SourceGit 2026.21, nouvelle version de l'amont.
Signalé dans l'issue #2. L'entrée du menu n'était proposée qu'en mode stable, au
motif que la disposition compacte ne donne à un chemin aucune voie à laquelle
s'accrocher : il occupe le rang qu'il tient parmi les chemins vivants. C'est
vrai, et hors sujet — le rang zéro est un rang comme un autre, et dériver
hors de lui est précisément ce que le mode compact fait. C'est donc là que
l'épingle vaut le plus.
Épingler signifie ici une seule chose : un chemin tient le rang zéro, tous les
autres se décalent d'une colonne vers la droite, aussi longtemps que ce chemin
vit.
L'épingle ne se résout que depuis l'épingle. Le mode stable retombe sur la
branche courante, ce qui est juste là-bas puisqu'il réserve une voie dans tous
les cas. Ici ce serait faux : sans rien d'épinglé, la disposition compacte doit
rester à l'octet près celle de l'amont, et un tel repli la déplacerait pour tous
les dépôts d'un coup.
Le chemin épinglé prend le commit qu'il atteint, quel que soit son rang.
Laissé au parcours, une branche qui fusionne peut être trouvée la première,
devenir la ligne maîtresse, et le chemin épinglé mourir dedans — lâchant la
colonne de gauche au milieu du tronc auquel il était accroché. Ce cas apparaît
dès que la tête d'une branche de travail est plus récente que celle du tronc,
c'est-à-dire ordinairement.
Au-dessus de la tête épinglée, rien n'est réservé : une colonne de gauche vide,
c'est ce que fait le mode stable, et dans une disposition dont tout le propos est
qu'il n'y a pas de trous, cela passerait pour un défaut. Le prix est que les
autres chemins se décalent d'une colonne sur la ligne où l'épingle commence à
s'appliquer.
Quarante-cinq commits de l'amont, dont une refonte de la barre latérale du dépôt
— elle est désormais toujours visible — une refonte de la page « Modifications
locales » avec un mode d'affichage unique pour toutes les listes, du travail sur
les worktrees, et la signature des paquets macOS côté amont.
Le placement compact du graphe reste identique à l'octet près à celui de
l'amont 2026.21 : 6130 lignes comparées — 3000 marges par commit, 67 chemins avec
tous leurs points, 3000 points de commit, 63 liens. La référence a été
reconstruite depuis l'amont lui-même plutôt que reprise de la version
précédente : après quarante-cinq commits, un écart aurait pu venir de l'amont
autant que de nous.
Empreinte de l'épinglage sur les fichiers de l'amont : soixante-quatorze lignes
ajoutées et quatre modifiées dans un seul fichier.
Une disposition qui n'offre aucune voie à laquelle s'accrocher offre quand même
un rang — et c'est tout ce qu'il fallait.
2026.20-3b.3
Le bouton « Télécharger » ne renvoie plus vers le navigateur : SourceGit récupère
le paquet qui correspond à la machine, vérifie son empreinte, remplace les fichiers
installés et propose de redémarrer.
Base : SourceGit 2026.20, inchangée.
Aucune publication de ce fork ne permettait jusqu'ici de distinguer un téléchargement
tronqué d'un téléchargement complet. Le workflow de publication calcule maintenant un
fichier SHA256SUMS et l'attache aux dix paquets.
Il est calculé avant la création de la publication, parce que c'est la seule
occasion : une publication est immuable, et rien ne peut lui être ajouté après coup.
Ce que cette empreinte prouve, c'est qu'un paquet est arrivé intact. Elle ne dit pas
qui l'a produit — les sommes sont publiées à côté des fichiers qu'elles couvrent.
C'est le travail d'une signature, et ce fork n'a pas de clé.
Le paquet est choisi selon le système et l'architecture, téléchargé dans le cache,
comparé à son empreinte, puis posé sur l'installation.
Rien n'est jamais écrasé. Chaque fichier est d'abord renommé de côté, et le nouveau
copié dans le nom qui vient de se libérer — la même asymétrie qui permet de renommer un
exécutable en cours d'exécution mais jamais de le supprimer. Un échec en cours de route
défait les renommages : l'installation est l'ancienne ou la nouvelle, jamais un mélange.
Le redémarrage relâche le verrou d'instance unique avant de lancer. L'ordre inverse
a l'air de fonctionner et ne fonctionne pas : le nouveau processus passerait ses
arguments à l'ancien puis s'arrêterait, laissant l'ancienne version au premier plan.
Une installation par paquet. Un .deb ou un .rpm appartient au gestionnaire de
paquets. Aucun fichier n'est touché, et aucun téléchargement n'est proposé non plus :
donner un AppImage à qui a installé un paquet système répondrait à côté.
Un dossier où l'on ne peut pas écrire. Tranché en écrivant un fichier sonde, pas en
comparant à une liste de chemins protégés — qui manquerait la copie installée par un
autre compte.
Une empreinte qui ne correspond pas. Le téléchargement est supprimé. Il n'y a pas
d'« installer quand même ».
Cette version est la première à publier ses empreintes. Elle peut donc mettre à jour
vers les suivantes, mais aucune version antérieure ne pourra se mettre à jour vers elle
automatiquement : il n'y avait rien à vérifier.
Le remplacement sur place couvre Windows, le bundle macOS et l'AppImage. Les décisions
qui engagent des fichiers reçoivent le système, le chemin du processus et la variable
APPIMAGE en paramètres plutôt que de les lire, ce qui permet de les vérifier hors de la
plateforme concernée — mais seul le chemin Windows a été éprouvé en conditions réelles.
Empreinte sur les fichiers de l'amont : deux lignes modifiées et quatre ajoutées
dans un seul fichier XAML.
Le placement compact du graphe reste identique à l'octet près à celui de l'amont.
Une mise à jour qui remplace un exécutable n'a le droit d'exister que si elle sait
aussi refuser de le faire.
2026.20-3b.2
La ligne « Modifications non commitées » du graphe ne se contentait plus d'exister :
la sélectionner remplit le panneau de détail.
Base : SourceGit 2026.20, inchangée.
Sélectionner cette ligne affichait jusqu'ici un panneau vide. C'était voulu — elle ne
correspond à aucun objet du dépôt, et tout ce qui suit un commit sélectionné va le lire
— mais « rien » répondait mal à une ligne dont le propos est qu'il y a quelque chose.
Aucun commit à lire, donc rien n'est demandé à git : les deux listes de la copie de
travail sont déjà chargées par la page d'à côté, et le panneau les emprunte.
Indexé et non indexé n'en font qu'une seule liste, parce que « ce qui n'est pas
encore commité » est une seule question. Un fichier peut être des deux côtés — modifié,
à moitié indexé, puis re-modifié — et il n'apparaît qu'une fois, du côté non indexé :
c'est celui qui diffère de ce qu'un commit enregistrerait. Ce choix décide du diff
demandé à git, donc il est vérifié plutôt que supposé.
Cliquer un fichier montre son diff. Le panneau suit la copie de travail : éditer un
fichier pendant que son diff est ouvert recharge la liste sans perdre la sélection, et
un fichier qui disparaît emporte son diff.
Seul l'onglet Changements est actif. Info n'aurait ni auteur, ni date, ni message
à montrer, et Fichiers liste l'arbre d'une révision qui n'existe pas davantage. Un
onglet qui s'ouvre sur du vide est pire qu'un onglet visiblement éteint.
Le panneau est en lecture. On voit, on ne manipule pas : indexer et abandonner
restent sur la page Modifications locales, plutôt que deux vues sur le même modèle à
deux endroits de la fenêtre.
Empreinte sur les fichiers de l'amont : vingt-huit lignes ajoutées dans un seul
fichier XAML, le gabarit qui rend ce panneau. Rien de supprimé, rien de modifié.
Le placement compact du graphe reste identique à l'octet près à celui de l'amont.
Une ligne qui ne correspond à rien dans le dépôt peut quand même dire ce qu'elle
représente — à condition de ne rien demander à git.
2026.20-3b.1 — La page a bougé, le graphe n'a pas bronché
Première version du fork sur SourceGit 2026.20, dont le mainteneur a profité pour
redessiner la page dépôt. Le suffixe repart donc à 3b.1.
Tout ce que ce fork ajoute reste éteint par défaut.
Ce que 2026.20 apporte
La page dépôt redessinée. La barre latérale se replie, et les boutons qui ne
concernaient qu'une sous-page sont partis la rejoindre : Plus d'options sur la page
Historique, Tout abandonner sur Modifications locales, Vider les remises sur Remises.
Pousser au bon endroit. La configuration branch.<nom>.pushRemote est respectée —
utile pour une branche créée par gh pr checkout — et l'URL de push d'un dépôt distant
se change depuis son menu contextuel.
Blame revu. Ctrl+clic (⌘ sur macOS) sur un SHA reconstruit les données de blame ;
un clic simple navigue vers ce commit dans l'historique. Les deux surlignent ce qui en
vient. Corrigé au passage : les données étaient fausses quand la première ligne du
fichier était vide.
Divers — les fichiers .diff sont acceptés comme patchs, les groupes de dépôts
peuvent se créer d'après le dossier de clonage, la sélection des changements a été
réécrite, un plantage d'AvaloniaEdit corrigé, et AvaloniaUI passe en 11.3.22.
Notes complètes de l'amont :
https://github.com/sourcegit-scm/sourcegit/releases/tag/v2026.20
Ce que ce fork ajoute
Le graphe. Placement stable des voies, colonne branche / tag avec le propriétaire
déduit, colonne graphe séparée, règle colorée par branche. Puis : n'afficher qu'une
branche, garder la principale dans la première colonne, les remises comme nœuds pendus
au commit où le travail s'est arrêté, et le travail non commité en tête — point ouvert,
sujet en italique.
Les forges. Un compte par forge, les branches marquées quand une demande de tirage
est ouverte, la liste des demandes dans le panneau gauche, et ce qui reste entre une
demande et sa fusion : build, revues, fils de discussion. GitHub, GitLab, Azure DevOps,
Gitea et Bitbucket.
Le panneau gauche. Masquer les sections dont un dépôt n'a pas l'usage, avec une
rangée collée au pied pour les ramener.
Les branches mortes. Une fenêtre qui liste les branches locales sans équivalent
distant et coche celles qu'on peut supprimer sans rien perdre.
Les conflits. Taper dans le panneau Résultat une fois tous les blocs tranchés.
Le confort. Dupliquer une entrée dans chaque liste à plus et moins — comptes,
services d'IA, modèles, actions, suivis de problèmes.
Correction
Un dépôt dont le nom contient un espace ne montrait aucune demande de tirage. Son
nom arrivait déjà encodé et repartait échappé une seconde fois : la forge répondait 404
sur un dépôt qui n'existe pas, et un 404 ressemble à « aucune demande ouverte ». Azure
DevOps est le seul à autoriser des noms qui se lisent comme une phrase, ce qui explique
que personne ne l'ait vu pendant quatre versions.
Sous le capot
Le portage n'a pas rejoué nos soixante-et-onze commits : la refonte de la page déplaçait
leurs points d'accroche, et les rejouer aurait voulu dire re-décider vingt-sept fois les
mêmes placements dans des états qui n'existent plus. Chaque accroche a été posée une
fois, contre le code qui sort réellement.
Et le placement compact du graphe est identique à l'octet près à celui de l'amont —
chemins, points, liens et marges par commit, sur trois mille commits. C'est l'invariant
de ce fork, et c'est ce qui le rend défendable.
2026.19-3b.4
Le fork annonce enfin ses propres versions
Base : SourceGit 2026.19.
Elle était éteinte depuis le début du fork, et le drapeau n'en était pas le seul
obstacle. Elle lisait le fichier de version de l'amont et son bouton de
téléchargement menait à la page de l'amont : comme ce build porte le numéro de
version de la release dont il est parti, elle aurait annoncé la prochaine version
de l'amont et invité à installer l'application d'origine par-dessus celle-ci.
Trois choses ont bougé, réunies en un seul endroit : ce qui est lu, où mène le
téléchargement, et comment deux versions se comparent.
La comparaison est la partie qui ne pouvait pas être simplement redirigée.
L'amont lit le tag comme un numéro de version ordinaire, ce qui échoue sur
v2026.19-3b.1 — et l'échec est avalé par le catch de la vérification
elle-même, donc le mécanisme aurait été silencieusement mort plutôt que
visiblement faux. Ce sont les tags qui sont comparés désormais, pris de la chaîne
que git describe inscrit déjà dans le binaire : le numéro d'assemblage doit
rester numérique et ne sait donc pas distinguer -3b.1 de -3b.2.
Deux versions du même mois portant des libellés différents restent
incomparables : rien dans le schéma ne dit si -3b précède -4a, et deviner
proposerait un retour en arrière comme une mise à jour.
À chaque démarrage, là où l'amont demande une fois par jour. Le rythme
quotidien convient à une application qu'on ouvre quand on en a besoin ; celle-ci
reste allumée des jours, et « une fois par jour » y devient « presque jamais » —
la vérification tomberait le matin où l'application a été lancée, puis plus rien
de la semaine.
La fenêtre annonce aussi la version courante par son tag exact, là où l'amont
n'affiche que l'année et le mois : le seul morceau du numéro qui ne dit pas ce
qu'on a.
Contrairement au reste de ce fork, c'est allumé par défaut. La case
« Vérifier les mises à jour au démarrage » des préférences l'éteint.
Rien ne s'installe tout seul : la fenêtre ouvre la page des releases dans un
navigateur.
Empreinte sur les fichiers amont : trois fichiers, neuf lignes. L'entrée de menu
et la case des préférences reviennent d'elles-mêmes, toutes deux déjà liées au
drapeau de compilation — aucun XAML, aucune chaîne de locale n'a changé.
Une mise à jour qu'on ne sait pas ordonner ne doit pas être proposée.