1 All this is assuming operation against a custom gotd(8) server which
2 would queue up incoming commits and attempt a 'trivial-rebase' operation
3 for each commit in sequence. Commits which fail 'trivial-rebase' are
4 rejected and reported as 'out-of-date' to the client.
6 'trivial-rebase' merges trees successfully as long as all file content
7 changes apply to the expected 'base blob' content (which implies a
8 conflict-free file merge according to diff3), all added blobs get
9 added where no blob exists yet, and only existing blobs get deleted.
11 (As an analogy, this part of gotd(8) would operate roughly like some
12 sort of Gerrit server with merge strategy set to 'rebase-if-necessary',
13 but without a code review UI and without Java.)
15 gotd(8) would also regulate read/write access to branches and perform
16 various sanity checks on commits: require a log message, reject merge
17 commits except where necessary (e.g. merges of vendor branches), ...
19 Another responsibility of gotd(8) would be to keep repo mirrors in sync.
21 ---
23 got pull:
25 fetch latest master branch from server to local origin/master
26 origin/master has new commits
27 if fast-forward possible:
28 set master -> origin/master
29 if running in a worktree: {
30 if fast-forward was possible:
31 automatically run 'got update' ('got pull' implies 'got up')
32 else:
33 attempt server-style trivial-rebase of master onto origin/master
34 if success:
35 set work tree's branch to rebased master branch (implied got up -b)
36 else:
37 require manual rebase + resolve conflicts
38 } else:
39 existing worktrees will have to be updated/rebased manually
41 ---
43 got push:
45 attempt push + trivial-rebase on server
46 out-of-date ? -> require 'got pull'
48 ---
50 "push by default" commits allow for "branchless" development (committing
51 local changes against a central server and local repo at the same time)
53 got checkout
55 work work work
57 get OKs for your local changes!
59 got OKs?
60 (optionally: stage OK'd changes with 'got stage')
61 got commit
62 create temp commit object; attempt push + trivial-rebase on server
63 if success:
64 temp commit becomes new head of local master
65 optionally, user may run 'got pull' to rebase local version of master
66 else:
67 (require unstage if changes were staged)
68 require got pull
69 try to commit again
71 (The fossil SCM has already implemented an implied-push-on-commit design.)
73 ---
75 repo/gotconfig syntax ideas:
77 [[[
78 # remote private mirrors
79 remote "openbsd_src" {
80 repository "src"
81 server
82 protocol ssh
83 user stsp
84 }
85 remote "my_src_mirror" {
86 repository "src"
87 server
88 protocol ssh
89 user stsp
90 }
92 # remote public mirrors
93 remote "public_src_mirror_anonssh" {
94 repository "src"
95 server
96 protocol ssh
97 user anonymous
98 }
99 remote "public_src_mirror" {
100 repository "src"
101 server
102 protocol https
103 # no authentication credentials for this remote since https is read-only
106 # read from local mirror and push to main server
107 # "sync-to" enables push by default with 'got commit'
108 # implied mapping: refs/heads/master <-> refs/remotes/openbsd_src/master
109 branch master pull-from my_src_mirror sync-to openbsd_src
111 # read from local mirror and push to local mirror
112 # "push-to" means commit locally, push manually
113 # implied mapping: refs/heads/my_branch <-> refs/remotes/my_src_mirror/my_branch
114 branch my_branch pull-from my_src_mirror push-to my_src_mirror
116 # same as above, pull from and push to local mirror:
117 branch my_branch remote my_src_mirror
119 # pull from and push to local mirror, use push by default with 'got commit'
120 branch synced_branch sync-with my_src_mirror
122 # read-only access, anoncvs-style
123 branch master pull-from public_src_mirror_anonssh
125 # read-only access over https
126 branch master pull-from public_src_mirror
127 ]]]
129 read-only config for just keeping /usr/src up-to-date with 'got update':
131 [[[
132 remote "origin" {
133 repository "src"
134 server
135 protocol https
136 mirror-references # map refs/* <-> refs/*
138 # mapping: refs/heads/master <-> refs/heads/master
139 branch "master" pull-from "origin"
140 ]]]
142 ---
144 Known implications of the above design for the implementation:
146 For each changed file, the 'trivial-rebase' operation needs to know the
147 ID of the blob which the new file content is based on ("base-blob ID").
148 Otherwise the out-of-dateness check in 'trivial-rebase' cannot work.
149 To satisfy this requirement, the client<->server protocol could require file
150 content modifications in a chain of commits being pushed to be expressed
151 in terms of GOT_OBJ_TYPE_REF_DELTA objects against known base blob IDs.
152 The client can read such base blob IDs from the latest commit in its copy
153 of the branch (e.g. refs/remotes/origin/master).
155 For simplicity, it might make sense to require the protocol to express
156 all file modifications in this way (GOT_OBJ_TYPE_REF_DELTA).
157 File additions could be expressed as a delta against the empty blob's hash
158 as a base. File deletions could send a delta which simply deletes all content
159 from the specified base blob in addition to an explicit 'delete' command to
160 allow the server to distinguish this case from an empty file on disk.
162 The above functionality could be implemented via a Git protocol extension.