-
Notifications
You must be signed in to change notification settings - Fork 580
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NIP-?? - WIP - Source Control Context #223
base: master
Are you sure you want to change the base?
Conversation
Are you working on this? I was working on a git plugin myself to use git repos stored on Nostr, but eventually decided it was a bad idea. And it is better to use normal git servers for git -- and have them be self-hosted or hosted on a variety of service providers, then use Nostr to send open issues, send patches, comment on patches and for repository discovery. I feel like these four functions above would make Nostr into an actually decentralized alternative to GitHub. Sending and applying patches was already done by @jb55 at http://git.jb55.com/git-nostr-tools, although it isn't being used much and I don't know if and how it could be improved. The reason why hosting git data directly on Nostr is a bad idea is that it would be extremely inefficient and storage requirements would be massive -- so relays would start blocking this kind of thing and we would have to use special relays designed just for git-nostr, and at this point it is better to just use normal git servers that already exist. Each with its own specialty. |
Agreed. Also the git protocol is a very efficient optimized for git, and git itself is already fully distributed. |
It's something I've dedicated some time to considering and working on a rough draft MVP implementation, but I wanted to open up the topic for discussion so I can hopefully learn from others that have given this some thought as well. I 100% agree on not hosting git repositories on relays by default. But the discovery of git repos on a relay that decided to host the data could be part of the NIP, as I've outlined in the draft. The NIP I began writing is outlining a way to store the context around source control. The draft here proposes using a tag in a specific kind to track the remote URL(s) for a given repository and creating an event from that. There will be metadata needed for tracking line-specific comments and that metadata could be included in the tags part of an Event of this kind. QQ: How do NIPs get numbered? |
@garyray-k I really like the idea of using nostr for context and keeping git hosting on git servers. I'm imagining a web-based nostr client that is essentially a github-inspired interface for working on PRs, issues, bugs, etc. Having a conversation around a PR on nostr is easy. But I think we would need some kind of nostr-enabled git hook to publish events that represent code changes on the remote repo, like this: The other thing is that making edits to a repository via this nostr-git-client seems like a potentially bad idea since putting private keys into nostr apps is still not ideal security-wise... NIP26 is out there now so maybe this is going to get better. But you could work on your repo from CLI or Git client as normal and see your pushed changes show up in nostr-git-client because they would be published to the PR by a hook on the remote repo. Not having the ability to directly interact with a repo via the client would make things like forking more difficult and clunky though... No forking, no committing, no merging, no creating new repos...
I was also wondering this 😅 |
I think the client would be responsible for this aspect finding new changes and updating the display. For an MVP, I envision the need for a client with two libraries, nostr and git (oversimplifying here). The git library is largely reading repositories and the nostr library publishes events with metadata to tie the event to a specific part of the git repo. |
I've been experimenting with this for a couple of days, and made decent progress, hit a few brick walls here and there but I thought I would give my input/conclusion. I started with a script that I could use to publish git refs (heads/tags) and objects (commits/trees/blobs) to a unique repository, the plan here was to get the event structures/schemas sorted before porting this script to a git-remote-helper so that we could simple push/fetch using git with a custom remote handler
After getting this far, I felt quite confident this could work, so I set about creating a client to interact with these events, that turned out pretty straight forward, I was able to create new repositories, update their details/settings etc... once a repository was created I could push branches up (with my dev script / not a git-remote-helper yet). At this point, I could browse all of my repositories and see all of their refs along with view the tree and latest commit of each ref. What I found was, all refs/objects are quite light minus blobs, moving over to packed git objects (deltas) rather than loose objects (no deltas) would certainly help here but then I thought about maybe storing blobs on the filesystem outside of the database (but this would rely on relay changes and I was trying to do this without introducing any new relay features than already proposed). Turned out it wasn't actually the end of the world with the files I tested on since my UI was only ever subscribing to blob objects when viewing a file. Few screenshots of the progress So things where looking good, however this was all just a big experiment, in the end I 100% came to the same conclusions that have been mentioned. Although I found there wasn't any performance issues with the test repos/branches I had published to a relay I'm sure with larger repositories it could be a concern. The funny thing is, before I started any development I wrote about a few options, having a git-server was the in between option All that said, it was a fun experience, I learnt a tonne of git internals along the way so it wasn't a complete waste of time but I think it might be time I hang up the boots on this one. If anyone want's to discuss how a git-server model may look, I would be up for discussing / working on something. |
What I've done is look through all the PRs, find the highest number, and go one higher. |
I like this draft and the initiative. Thank you @garyray-k. I agree with the idea of having a dedicated kind for "merge requests" (and possibly one for "issues"?), but the responses to these seem to me to fit better in It would be nice to have these notes -- i.e. discussions about a merge request -- to show up in the normal "social" feed of users, right? And then social feed users could click on the context to see the event they were replying to and then what would they see? An event (that they would not understand) specifying a merge request. Do you think this is good or bad? Did you think about that? |
It seems we are all here in agreement that relays should be a transport layer rather than a storage medium. This points to git servers holding the data and communicating over Nostr with git clients. It can connect with @gayray-k suggestion above. |
@hendore Nice research! I'm glad you concluded that relays mustn't hold repos, but there will likely be relay servers that do both for hosting simplicity.
I think this will happen with
I will have to do some research on how clients are handling the "content" field. My initial thought would be to standardize the
Git already handles authentication and even has mechanisms for separate authors and committers. The goal of this NIP would be to anchor series of events to a single git "thing". The simplest I reasoned about was a merge request. |
That's kind of what I was thinking. |
My purpose with "Nostr Auth" is to separate the constant public point of contact from a dynamic, nonconstant uncensorable IP generated for a git session. At the first simple stage, this IP may be the IP of a git server that is generated by a VPN per connection request. At later stages, the entire client-server git communication can be done by both the client and the server polling on private messages sent to them and transmitting data over relays with no server IP involved. |
@ofer-elrom |
Thank you. I understand. Sorry for the distraction of focus. |
I like were this is going. Maybe https://github.com/zw/bitcoin-gh-meta can give some inspiration on the required context schemes. |
Someone brought up a good point of consideration: how do disparate notes maintain their tie together? Example: How do we maintain this context? |
Nostr provides redundancy if you utilize it. Dev B should post to more than one relay. Now the trick here is that people following the repo need to see Dev B's note, so instead of what we do for a microblog (everyone writing wherever they prefer), repos should probably be hosted on a (per-repo) well defined set of relays (but more than just one) chosen by the owner of the repo, and these relays configured in a way that they allow access appropriately to this repo. The NIP-65 model surely won't work. It's not 1-to-many, it's many-to-many. |
my proposal for Git:
|
The one assumption github makes about the git repository itself is there is only one official location to push and pull from. This makes sense in the case of something that's intended to be a frontend to a git server, but it doesen't leverage the decentralized intent behind git. Github stores PRs on the central repo on a branch, which requires write access to the central repo. It makes more sense in decentraland to point to a branch on a git remote rather than requiring the project owner to manage a ratsnest of ACLs for everyone that wants to push. Github solves this by allowing references to forks inside the platform, but this is clunky and clutters your own account and if you dont intend to actually fork the project then you will never make use of all of the other features in your own account. It would be nice to have a "pure" github URI place to store your public copy of the repo without needing to access it through a bloated CMS like github. This could be as simple as your own ssh server and then anonymous read-only access is provided to the "Project context" as (multiple?) URI and sshkey fields. Alternatively, there might be future integration with git-torrent to host the central repo. In the case of building it on a nostr backend, each PR should point to a unique http/ssh uri (which does not preclude using the central repo). |
This comment was marked as spam.
This comment was marked as spam.
The owner of the root repository Event would be listing the remote locations that are canonical. How they manage ACL for those is outside the scope of this NIP.
This already exists. You can host remote repos outside of github that people can clone from. This is a decent article describing the process (https://www.inmotionhosting.com/support/website/git/git-server/). And if you look at a GitHub URL, it's a remote URL + file path. |
This comment was marked as spam.
This comment was marked as spam.
How do we feel about adding the POSSIBILITY to include the patch in a merge request event somehow? It would enable users to create merge requests without having write access to any git server. Could be a confusing first time experience if you need to find a git server to host your changes. Clients would probably be forced to have default git servers for their users just like with images now. The obvious downside is that including the patch would create large events. Completely agree with the general sentiment that the relays should not store the repository. Sending patch files around is the OG way to use git so it could make sense to support them in this brave new word. Maybe another kind and another NIP? For example this is the patch for this PR https://patch-diff.githubusercontent.com/raw/nostr-protocol/nips/pull/223.patch |
I also think this NIP shouldn't be using number 69. Better leave that number for something less important and more playful. |
Hey everyone, im creating a new NIP like this one because we CANT implement an exact git over Nostr because of commit chains because it needs order which cant be possible on an async network. |
I created a proof of concept git integration for nostr. You can use it to create a git repo server that takes its config from nostr. By issuing commands to a relay you can trigger the creation of git repositories and manage the permissions of these repositories. Authentication is handled by associating your nostr profile with an SSH key. A quick demo video is here https://www.youtube.com/watch?v=G-WzlC8XfW4 The source code and documentation is here. https://github.com/spearson78/gitnostr |
The project mentioned in the link seem to be moving forward with similar concepts in mind. I think it may be good if you joined: |
this is really cool @spearson78, should we team up and join forces with nostrgit.com? we're currently discussing backend and CLI |
Everyone check #358 |
Doesn't a patch based workflow work better over nostr? Please correct me if I'm wrong. Sending patches is just sending events. So Gerrit over Github? Essentially the email lists based flow except not email. Just a matter of directing Gerrit backend to look at Nostr for new content? |
Yes, @npub1zenn0, I think you are right. |
PRs are still useful though. The PRs over nostr demo I was tinkering with looked similar to this one:
|
Patches fit very well with nostr and I think we should support it for several reasons (see #223 (comment)). On the other hand PRs is the dominant way people interact with git these days. PRs are just like @jb55 says still useful. But most of all they are familiar. We might be best of supporting both references to commits on git servers and patches in the protocol but having in mind that it should be easy for app developers to present everything as PRs because that is the most familiar. |
Right, pull requests are indeed the de facto way at this time. However, making Gerrit work over nostr should be the low hanging fruit. I would like to guess it possible to have an MVP Gerrit instance open with a separate micro service that looks at nostr and posts into the Gerrit instance as admin, in reasonably short time. Then again if a PR version is done and well, could do the same with a gitlab instance. And on this NIP: Git LFS was brought up npub1zenn0/go-git-nostr#1 . There should be a |
Thanks @npub1zenn0 yes a pointer is exactly what’s needed |
What is the difference between a PR and a patch? To send a PR you must have a git server to point to, but to send a patch you don't need that? In terms of UX both should be equivalent, no? You send the patch and people can comment on the patch and ultimately opt to "merge" the patch or not. |
I make the distinction in that a patch is something you overwrite (mimicking force push) if you change it, while a PR is something with a branch that you push new commits onto. |
patches are just a textual diff to a file, and applying patches has no link to the previous history. In certain contexts merging a branch is the only allowed workflow to preserve history and auditability. bitcoin-core works this way. Also sometimes you need to merge large chunks of code at once. Linux/linus himself uses PRs to merge large subtrees of changes, whereas maintainers collect patches into their branches for Linus to merge. They serve two different purposes, I don't think there should only be patches on nostr, since it doesn't cover the uses cases of merging large subtrees and preserving commit history. |
Great conversation https://github.com/icyphox/legit/blob/master/go.mod#L7 this might help !! At least for something to experiment on …. it does unified diff . The way it does git diffs and merge is clean, and it just happens to be a git server and gui in 100% golang . It’s highly stable. I have been using this for a few months. |
Excited to see such an active discussion. This is slightly alternative architecture and how a NIP like this could fit: blob storage and retrievalThere are different viable models to store, serve and retrieve data in a way that present like a standard git server/client interaction. This may be using a standard git server on a niche relay with a nostr permissions wrapper, or using a client to mimic this delivery whilst abstracting an alternative model under the hood. There needs to be experimentation because getting the incentives right for actors to serve the underlying data is challenging given that storage and bandwidth is expensive. Interactions with git servers and relays should be trust minimised. Nostr events following a NIP standard should prove every change made is authorised by an maintainer. Other clients and relays that want to sync with the git server which was pushed to must be able to pull the update from the git server, verify it using the nostr event before writing it. Clients cloning a repo should be able to use available events to validate they have the complete and unadulterated repository as of the date of the last Nostr event they received. Some models for delivering git data might use Nostr events to store git metadata and store blobs using torrents. Some might use a standard git server. Both would support the above NIP and would only accept write changes that have been signed. Bridges could enable repositories to be stored using multiple models. This would reduce entry barriers repository maintainers wouldn't have to choose one model. Collaborative Software Development ExperienceA vibrant array of clients, serving different aspects of the software development collaboration experience will emerge. micro-apps might address a single feature and other clients might support many: Kamban boards, issue tracking, comments on lines of code, PR review, etc. Clients would utilise anchor points with a standardised referencing schema outlined in a NIP for elements both inside a git repository (lines of code, commits, etc) and outside the git repository (PRs, issues, kamban boards, etc). These NIP(s) would facilitate innovation at the storage and retrieval layer and the collaboration experience layer to proceed independently. Any thoughts? Note: I just published a NIP-23 article entitled The Bull Case for a GitHub Alternative on Nostr, which might add some context. |
Start with a Unified Diif capability that is the core of what git does , so that just like git the client can diff and send in patches and the relay can apply those patches. |
@gedw99, if we work purely off a patch model:
I wrote a follow up article entitled Key Challenges for a GitHub Alternative on Nostr. In it I suggest standardising the 'anchors' between the social experience and elements in a repository (eg. commits or line of code) as the first standard to agree in this usecase. This could be a soft-standard or a NIP. Doing this would enable developers working on the social experience and those working on the git repository side, something to work off. |
thanks @DanConwayDev just read the blog and i see the history rewrite aspects and time ordering. very well written. Ordering of mutations in an offline first collaborative system is an age old problem ( CRDT, etc etc ). If we can get this right, then rewrite history with UDIff presents a archetype for all collaborative systems with a git baed file system ? |
@gedw99 thanks for you feedback.
We could follow the model I outlined in 'The Conflicting Change Problem' section of the article I referenced above, with each 'Authorisation Event' referencing the previous mutation it was building upon. Do you think this model is workable? It is dependent on solving the 'Group Authorisation Problem' which I hope to be publish an outline solution to soon.
We could establish a standard for a new type of patch that supports all possible mutations of the repository. This could be based on the existing git patching model and UDiff. a client wrapper could simulate pushing and pulling from a remote git server whilst operating entirely through patches. I still feel patching is an inefficient model and the state reversion problem is better solved in a more elegant way. For example, Authorisation Events compactly including diffs in git/refs. The beauty of a standard for Authorisation Events is that the patch model, as well as other models could be built out and maintain compatibility as I discussed in the 'The Interoprablilty Problem' section of the article. |
Hey @DanConwayDev Can i answer in general for now, as i read your blog article and the other things and it makes sense but the jargon is a little vague. If we don't allow for offline mutations, which we don't AFAIK. Then it is a matter of ensuring all mutations are globally ordered, just like any async message broker architecture The tricks i know to do that are:
Then your all set.. You can also then run subscription queries, where a query for data causes the actor to be added to the presence map and so then when any data changes on the server / relay all actors get a CDC like CUD event, which they use to update their local copy of the data. Very standard stuff for this area. Why do this ? because then the clients never have stall data, so when they later send a mutation, it's a mutation based on up to date data, and so you massively reduce the number of validation through backs from the server. I guess you can think of this as a best practice way of ensuring linearizability, but not inside a DB but outside one. The old "Turning the database inside out" by Martin Kleppmann ... Web Clients - You can do this inside anything. These days a Service worker PWA for example. So this model support web apps too. Indexed DB limits you to 50 MB non deterministically, so some cache eviction strategies are needed. I only say this because i see most Nostre use cases with their only being a Relay, and then Clients. Some Use cases however might be a proper durable server being fed off the relay too and then clients talking t the Server ? don't know.... I hate being so general about he patterns, but again its seems like Nostr is really imitating this classic pattern above. Hope this is helpful in some way ?? |
@gedw99 Thanks for taking the time; that was helpful. I thought it best to flesh out my proposition a bit more to allow for a more specific critique. My proposal for authorisation groups is outlined in this NIP draft. I have traded-off simplicity of design and implementation against speed of state change confirmation. The needs here are medium-low frequency of changes so I don't think change conflicts are going to be a regular occurrence. Most users interact asynchronously at low-frequencies with git services. CI/ID and webhooks less so... |
hey @DanConwayDev I see what you mean about speed of changes being low and so mutations very likely to be ordered and life is good then. Its a good solution and i agree it's the least worst path forward. Its always "what is the least worst solution" in software and engineering :) CRDT etc is YAGNI if this works. thanks for taking what i said into consideration. |
https://ngit.netlify.app/ I wrote a prototype under the name ngit that builds on the patch model but brings it closer to PR workflow.
There are events for repos, branches, patches, PRs, merges and groups. A patch is always applied to one 'branch'. A 'branch' isn't reissued to refer to the latest commit like in git. Instead it is just an id linked to a repo that patches can be associated with. Merges indicate that a patch from one branch is applied to another branch. PRs indicate a desire to merge one branch into another. Comments and further patches can applied to a branch as the conversation around the an associated PR continues. Groups manage the permissions on branches so that maintainers and authors can add patches to PR branches and only maintainers can merge or commit directly to the main branch. This partially implements the Nostr Groups draft NIP. The patch application process is adjusted so that commit ids are preserved which addresses the history and audibility needs of projects like bitcoin core. |
hello hendore, is there a possibility to try out/download your client? I think the presentation is pretty good and I would like to work on it further. |
I laid down a rough draft of how we can decentralize source control context using nostr. I am opening this Work In Progress PR so I can share it with others and gather feedback, as I'm certain that I missed something in my initial thoughts.