À propos du projet
9vcs est un système de contrôle de version construit sur 9P, le protocole Plan 9, via la bibliothèque Go 9p de l'auteur. Il s'adresse à une petite équipe de confiance souhaitant un véritable contrôle de version sans plateforme d'hébergement. L'historique est conservé sous forme d'un ensemble de patchs adressés par le contenu plutôt que de snapshots ; le README renvoie vers PLAN.md pour le raisonnement conceptuel et se limite à l'utilisation pratique. Le vocabulaire n'est délibérément pas calqué sur celui de GitHub : il n'y a ni clone, push, pull, fork ou pull request, et un aide-mémoire fait correspondre les termes habituels aux équivalents de 9vcs.
Prérequis et installation
Le seul prérequis est Go 1.26.5 ou une version ultérieure. 9vcs et la bibliothèque 9p sur laquelle il repose sont écrits en Go pur utilisant uniquement la bibliothèque standard, sans démon, base de données ou services externes. Des binaires précompilés sont publiés sur la page Releases sous forme d'archives tar.gz pour linux/amd64, linux/arm64, darwin/arm64 et darwin/amd64, chacune avec une somme de contrôle .sha256 pour vérification ; l'archive contient le binaire, la LICENSE et le README. La compilation à partir des sources se fait via une seule commande go build contre cmd/9vcs. Alternativement, certains installateurs sont disponibles.
Flux de travail solo
Après avoir exécuté init dans un répertoire, status affiche une ligne par chemin modifié en utilisant A pour nouveau, M pour modifié, D pour supprimé et U pour conflit non résolu ; il ne rapporte que ce qui est « sale », pas le diff. Les déplacements ne sont pas suivis comme des renommages — un fichier déplacé apparaît comme une suppression plus un ajout, correspondant à la manière dont le patch sous-jacent le stocke. diff montre les changements au niveau des lignes dans l'arbre de travail, peut effectuer un diff contre un autre point, ou peut comparer deux points directement sans impliquer l'arbre de travail. log liste les patchs enregistrés, du plus récent au plus ancien, avec l'auteur, l'empreinte ou le statut de la signature, et les chemins touchés. record crée un patch. Il n'y a pas de zone de transit (staging area) ou d'étape d'index : l'arbre de travail lui-même sert de zone de transit, et record le compare au head actuel.
Branches et fusion
branch liste, crée à partir de HEAD ou d'une autre branche ou d'un hash, et checkout bascule ou crée et bascule avec un flag -b. La fusion produit de vrais conflits de graphe de patchs — bifurcations au niveau des lignes, conflits binaires avec un fichier sidecar de comparaison, et conflits modification/suppression — plutôt qu'un simple diff textuel à trois voies. Une fusion propre est finalisée avec record. Une fusion conflictuelle laisse des marqueurs de conflit en ligne dans les fichiers texte affectés, tandis que les conflits binaires reçoivent un fichier sidecar nommé d'après le chemin et un hash court pour comparaison ; l'utilisateur édite puis enregistre. Une fusion peut être annulée, restaurant l'arbre de travail exactement dans son état pré-fusion et effaçant l'état de fusion, que la fusion provienne de la commande merge ou de apply.
Motifs d'exclusion
Un fichier .9vcsignore à la racine du dépôt fonctionne comme .gitignore et est destiné à être enregistré et partagé. Un motif par ligne ; les lignes vides et les commentaires commençant par un hash sont ignorés. Les motifs sans slash correspondent à n'importe quelle profondeur, les motifs contenant un slash sont ancrés à la racine du dépôt, et un slash final restreint la correspondance à un répertoire réel. La négation avec un point d'exclamation et les motifs double-étoile ne sont explicitement pas supportés. Les motifs d'exclusion empêchent seulement les nouveaux fichiers d'apparaître dans record et diff, et l'ajout d'un motif ultérieurement ne rendra jamais un fichier déjà enregistré comme supprimé.
Utilisation en équipe
Chaque installation génère une paire de clés Ed25519 à longue durée de vie lors de la première utilisation, et identity show affiche l'empreinte que les coéquipiers s'échangent hors bande pour s'autoriser mutuellement. Celui qui héberge l'historique partagé exécute serve sur un port ; le serveur lit .9vcs/authorized-peers dans le dépôt actuel, une ligne empreinte-et-permission par coéquipier, où les permissions sont read (historique en lecture seule), propose (lecture plus publication d'un bundle signé dans la zone des offres), et write (tout, y compris le déplacement d'une référence de branche). Il n'y a pas de commande add-collaborator — il s'agit simplement d'éditer ce fichier — et le fichier est lu une seule fois au démarrage, donc les changements nécessitent un redémarrage, ce qui est important lors de la révocation d'une clé potentiellement compromise.
serve s'exécute au premier plan sans démon d'arrière-plan. Un push réseau refuse de déplacer la branche actuellement checkoutée sur la machine serveuse, donc l'hôte doit garder une branche différente checkoutée ou utiliser un répertoire réservé au service. Un nouveau coéquipier commence avec init et import, en passant l'empreinte d'un pair, un hôte et un port ainsi qu'un nom de branche ; import est uniquement en fast-forward et récupère la branche ainsi que chaque patch et blob dont elle dépend transitivement. reconcile est la commande de synchronisation continue : elle récupère (pull) si le pair est en avance, pousse (push) si le côté local l'est, et en cas de divergence réelle, récupère ce qui manque et demande à l'utilisateur de checkouter et fusionner localement plutôt que de résoudre via le réseau. Les deux commandes peuvent épingler explicitement l'empreinte d'un pair, sinon elles utilisent un magasin local de confiance au premier usage (trust-on-first-use) qui demande une confirmation une seule fois pour une nouvelle adresse, vérifie silencieusement les adresses connues, et refuse bruyamment une empreinte qui change soudainement.
Échanges hors ligne et propositions
Les bundles déplacent les changements sans aucun serveur actif : export écrit un bundle signé dans un fichier pour un envoi par email, chat ou support amovible, et le destinataire l'inspecte avec bundle show (signataire, message, patchs), l'importe pour vérifier la signature et le stocker localement sans toucher à aucune référence, le examine avec diff, puis l'applique et l'enregistre. Import ne déplace jamais une référence par lui-même. Les pairs ayant seulement la permission propose peuvent soumettre directement via offer, qui poste un bundle signé sur le serveur du mainteneur ; le mainteneur liste les offres en attente, en applique une pour la récupérer, la vérifier et la stocker localement, l'intègre avec apply, et la supprime de la file d'attente. Parce que les offres existent uniquement dans l'espace de noms du serveur actif, le mainteneur se connecte à sa propre instance serve et a donc besoin de sa propre empreinte dans le fichier authorized-peers également.
Fenêtres sur 9sh et gestion des espaces de noms
Normalement, le dépôt est résolu en remontant depuis le répertoire courant, comme git. À l'intérieur de 9sh, un shell de style Plan 9, le flag -C placé avant le nom de la commande offre une seconde route : il teste le chemin contre l'espace de noms 9sh en premier — un chemin relatif sous local, ou un chemin absolu pouvant correspondre à tout ce que 9sh a lié — avant de revenir à un chemin OS littéral. En dehors d'une session 9sh, le flag se comporte comme git -C.
Récupération
Les procédures de récupération documentées couvrent l'annulation d'un merge ou d'un apply, l'enregistrement ou le rejet manuel de changements non commités qui bloquent un checkout, merge ou apply, la restauration de chemins individuels à leur état enregistré au head avec restore (un chemin sans état enregistré est supprimé, donc annuler un renommage signifie nommer les deux chemins), et le ré-épinglage de l'empreinte d'un pair qui a légitimement changé.
État du projet
Le README distingue l'utilisation de 9vcs avec une équipe du développement de l'outil lui-même, qui suit un développement basé sur le tronc (trunk-based development) avec des branches à courte durée de vie, un master protégé où personne ne pousse directement, une CI couvrant build, vet, gofmt et des tests avec détection de race avant la fusion, des fusions uniquement par squash et la suppression automatique des branches. Le versionnage suit semver pour les releases, actuellement dans la plage v0.x. En dessous de v1.0.0, il n'y a aucune promesse de compatibilité pour le format des patchs et bundles sur disque, qui peut changer sans chemin de migration ; à partir de v1.0.0, tout patch ou bundle enregistré sous un format publié restera décodable, les futurs changements incompatibles étant gérés par un dispatch de version réel et des outils de migration fournis. Un changelog enregistre le contenu de chaque release.
Comments
0 Rating appears after 10 ratings
Sign in to join the discussion.