Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

A free and open-source forge that lives in your Git repo.

Resolve a change request's head on the remote, not the clone

6755b7515c2e3e404e8325eabc0b1e0b74ab901f · Keenan Nemetz · 10d ago · parent 26c9be33

Resolve a change request's head on the remote, not the clone

`change new --head <branch>` resolved the branch in the local clone. A
clone that was behind recorded the old commit, and when that commit was
already in the base the request contained nothing — which is how #117
merged nothing, closed its issue, and left the work on a side branch.

- A branch's head is resolved with `git ls-remote` against the remote the
  metadata write pushes to, so the recorded commit is the forge's tip. If
  local and remote differ, the remote tip is recorded and stderr says so;
  a local-only branch is recorded with a note; `--no-push` may fall back
  to the local ref when the remote cannot be reached.
- A request whose head is already in the base (the same commit, or an
  ancestor) is refused before anything is written, for `change new` and
  `change update --head`. The base is resolved on the remote too: a
  feature worktree commits on its local base branch, so the local base can
  be the head itself and would call every request empty.
- The tag/commit path is unchanged: it still pins the request to that
  commit with no branch.

Tests cover a branch that moved after the clone, a local-only branch, a
head equal to the base, a head that is an ancestor of the base, and the
`change update --head` refusal. The head-resolution note is documented in
docs/change-requests.md.

server/integration_test.go +10−1

@@ -1108,8 +1108,17 @@ func TestRequestAuthorComesFromTheKey(t *testing.T) {
1108 1108 if _, errs, err := runGit(t, clone, "config", "user.name", "Keenan Nemetz"); err != nil {
1109 1109 t.Fatalf("config: %s", errs)
1110 1110 }
1111 // A request reviews a change, so it needs a head that is not already the base.
1112 runGit(t, clone, "checkout", "-q", "-b", "topic")
1113 if err := os.WriteFile(filepath.Join(clone, "readme.md"), []byte("hi\ntopic\n"), 0o644); err != nil {
1114 t.Fatal(err)
1115 }
1116 runGit(t, clone, "commit", "-qam", "topic")
1117 if _, errs, err := f.git(clone, "push", f.sshURL(f.repo), "topic:refs/heads/topic"); err != nil {
1118 t.Fatalf("push topic: %s", errs)
1119 }
1111 1120
1112 out, errs, err := f.cli(clone, "change", "new", "--title", "author from the key", "-m", "body")
1121 out, errs, err := f.cli(clone, "change", "new", "--title", "author from the key", "--head", "topic", "-m", "body")
1113 1122 if err != nil {
1114 1123 t.Fatalf("request new: %v\n%s", err, errs)
1115 1124 }