From: James Cook Subject: three bugs related to merge commits To: gameoftrees@openbsd.org Date: Mon, 13 Mar 2023 00:01:42 +0000 I recently noticed the following bugs. I just verified that they still happen with the lastest got, commit 264c43dd. Two of them have scripts to reproduce; the other's pretty simple. ** First bug: got ci doesn't properly check for updated-ness, and clobbers merge commit with surprising results A script to reproduce follows. First, though, a description. We set up the following four commits, where a commit "branch" from another branch got merged into the main branch. merge | \ 1 branch | / init Now, in another worktree pointing to the "1" commit, we make a change and run "got ci". This should fail because the worktree is not updated. Instead, the merge commit is forgotten, and we end up with: 2 | 1 | init As fallout from this strange situation, two weird things happen: - The commit "2" includes the changes from the commit "branch", even though they weren't in the work tree when we ran "got ci" to create that commit. - In the worktree pointing to the commit "merge", got up refuses to run, saying "got: work tree's head reference now points to a different branch; new head reference and/or update -b required" ---- BEGIN script ---- #!/bin/sh set -e mkdir bug;cd bug # Create a repo with an initial commit. gotadmin init repo.git mkdir init;touch init/f got import -m init -r repo.git init # For convenience, we'll use three work trees. for name in branch merge linear; do got checkout repo.git $name; done # Make a branch with one new commit. cd branch got branch aux echo 1 > on_branch got add on_branch got commit -m branch # Commit to the main branch; put that in the other two work trees. cd ../linear echo 1 > f got commit -m 1 cd ../merge got up # In the worktree called "merge", add a merge commit to main. got merge aux # In the worktree called "linear", add a commit *without updating*. cd ../linear echo 2 > f got commit -m 2 # First problem: # # Examine the commit that was created in the worktree at bug/linear. # Surprisingly, it adds the file "on_branch", but does not include # either the commit called "branch" or the merge commit in its history. # Second problem: cd ../merge got up # got complains: "got: work tree's head reference now points to a different branch; new head reference and/or update -b required" ---- END script ---- ** Second bug: can't send after merging origin/main This one's simpler. An argument could be made it's not a bug, but the behaviour is certainly different from git. - Clone a remote repo. - Make a change in the remote repo. - Separately, make a change in your local clone. - In the local clone, run got fetch then got merge origin/main. - Run got send. got send says: got: refs/heads/main: fetch and rebase required Coming from git, my expectation is that I can send the new commit since it includes the remote head in its history. If the goal of "got merge" is only to support vendor branches, then this behaviour might be reasonable, since it indicates a departure from that work flow: the remote main should appear in the "linear history" ignoring second merge children. Still, though, a different error message would help. ** Third bug: Can't merge a branch with identical content. Create two branches A and B, where A includes all of B's changes, but as different commit objects. Then try to merge B into A. Got complains: got: merge of refs/heads/aux cannot proceed: no changes to commit I do occasionally want to create merge commits like this. For example, it happened while I was cleaning up after I encountered the first bug above: I ended up with divergent commits making some of the same changes, and wanted to incorporate all of them into my commit graph for a historical record. Here's a script to reproduce; for simplicity, the changes are not just a subset but exactly the same. ---- BEGIN script ---- #!/bin/sh set -e mkdir bug;cd bug # Create and check out a repo with an initial commit. gotadmin init repo.git mkdir init;touch init/f got import -m init -r repo.git init got checkout repo.git; cd repo # Create a branch with a commit. got branch aux echo 1 > f got ci -m branch # Commit the same change (but different commit object) to main. got up -b main echo 1 > f got ci -m main # Try to merge. got merge aux ---- END script ---- -- James