Game of Trees Examples



These examples are supplemental documentation to the man pages, which are available both in the installed system and online.

Quick Links:

Comitting changes selectively
Amending the latest commit
Using got(1) with the ports tree


Working on a bug fix will often leave behind unrelated local changes, such as temporary debug messages. This section explains how isolated parts of local changes in a work tree can be committed in such situations.

Consider the following diff, which contains a workaround (disable MIMO) for a fictional bug in the iwm(4) driver. This workaround sits between two temporary debug messages:

$ got diff
diff a737ddea9a6b93fdcfad0176dad8d184b2e2138a /usr/src
blob - 335033d21091a23511403804f09d1548b109b104
file + sys/dev/pci/if_iwm.c
--- sys/dev/pci/if_iwm.c
+++ sys/dev/pci/if_iwm.c
@@ -4620,6 +4620,8 @@ iwm_add_sta_cmd(struct iwm_softc *sc, struct iwm_node 
 	uint32_t status;
 	struct ieee80211com *ic = &sc->sc_ic;
 
+	printf("%s: adding node for STA %s\n", __func__, ether_sprintf(in->in_ni.ni_macaddr));
+
 	if (!update && (sc->sc_flags & IWM_FLAG_STA_ACTIVE))
 		panic("STA already added");
 
@@ -4638,7 +4640,11 @@ iwm_add_sta_cmd(struct iwm_softc *sc, struct iwm_node 
 	}
 	add_sta_cmd.add_modify = update ? 1 : 0;
 	add_sta_cmd.station_flags_msk
-	    |= htole32(IWM_STA_FLG_FAT_EN_MSK | IWM_STA_FLG_MIMO_EN_MSK);
+	    |= htole32(IWM_STA_FLG_FAT_EN_MSK);
+#ifdef notyet /* FIXME: we are not yet ready for MIMO! */
+	add_sta_cmd.station_flags_msk
+	    |= htole32(IWM_STA_FLG_MIMO_EN_MSK);
+#endif
 	add_sta_cmd.tid_disable_tx = htole16(0xffff);
 	if (update)
 		add_sta_cmd.modify_mask |= (IWM_STA_MODIFY_TID_DISABLE_TX);
@@ -4675,8 +4681,11 @@ iwm_add_sta_cmd(struct iwm_softc *sc, struct iwm_node 
 	status = IWM_ADD_STA_SUCCESS;
 	err = iwm_send_cmd_pdu_status(sc, IWM_ADD_STA, sizeof(add_sta_cmd),
 	    &add_sta_cmd, &status);
-	if (err == 0 && status != IWM_ADD_STA_SUCCESS)
+	if (err == 0 && status != IWM_ADD_STA_SUCCESS) {
 		err = EIO;
+		printf("ADD_STA_CMD failed: add_modify=%d flags=0x%x\n",
+		    add_sta_cmd.add_modify, add_sta_cmd.station_flags_msk);
+	}
 
 	return err;
 }

Got offers several ways of committing this workaround in isolation.

One possibility is to stage the desired change with got stage:

$ got stage -p
-----------------------------------------------
@@ -4620,6 +4620,8 @@ iwm_add_sta_cmd(struct iwm_softc *sc, struct iwm_node
        uint32_t status;
        struct ieee80211com *ic = &sc->sc_ic;

+       printf("%s: adding node for STA %s\n", __func__, ether_sprintf(in->in_ni.ni_macaddr));
+
        if (!update && (sc->sc_flags & IWM_FLAG_STA_ACTIVE))
                panic("STA already added");

-----------------------------------------------
M  sys/dev/pci/if_iwm.c (change 1 of 4)
stage this change? [y/n/q] n
-----------------------------------------------
@@ -4638,7 +4640,11 @@ iwm_add_sta_cmd(struct iwm_softc *sc, struct iwm_node
        }
        add_sta_cmd.add_modify = update ? 1 : 0;
        add_sta_cmd.station_flags_msk
-           |= htole32(IWM_STA_FLG_FAT_EN_MSK | IWM_STA_FLG_MIMO_EN_MSK);
+           |= htole32(IWM_STA_FLG_FAT_EN_MSK);
+#ifdef notyet /* FIXME: we are not yet ready for MIMO! */
+       add_sta_cmd.station_flags_msk
+           |= htole32(IWM_STA_FLG_MIMO_EN_MSK);
+#endif
        add_sta_cmd.tid_disable_tx = htole16(0xffff);
        if (update)
                add_sta_cmd.modify_mask |= (IWM_STA_MODIFY_TID_DISABLE_TX);
-----------------------------------------------
M  sys/dev/pci/if_iwm.c (change 2 of 4)
stage this change? [y/n/q] y
-----------------------------------------------
@@ -4675,7 +4681,7 @@ iwm_add_sta_cmd(struct iwm_softc *sc, struct iwm_node
        status = IWM_ADD_STA_SUCCESS;
        err = iwm_send_cmd_pdu_status(sc, IWM_ADD_STA, sizeof(add_sta_cmd),
            &add_sta_cmd, &status);
-       if (err == 0 && status != IWM_ADD_STA_SUCCESS)
+       if (err == 0 && status != IWM_ADD_STA_SUCCESS) {
                err = EIO;
                printf("ADD_STA_CMD failed: add_modify=%d flags=0x%x\n",
                    add_sta_cmd.add_modify, add_sta_cmd.station_flags_msk);
-----------------------------------------------
M  sys/dev/pci/if_iwm.c (change 3 of 4)
stage this change? [y/n/q] q
$ 
The staged change can be seen with got status and got diff:
$ got status
MM sys/dev/pci/if_iwm.c
$ got diff -s
diff a737ddea9a6b93fdcfad0176dad8d184b2e2138a /usr/src (staged changes)
blob - 335033d21091a23511403804f09d1548b109b104
blob + 7ad0ed87af5ef451beba1224ca5186906881aba5
--- sys/dev/pci/if_iwm.c
+++ sys/dev/pci/if_iwm.c
@@ -4638,7 +4638,11 @@ iwm_add_sta_cmd(struct iwm_softc *sc, struct iwm_node
        }
        add_sta_cmd.add_modify = update ? 1 : 0;
        add_sta_cmd.station_flags_msk
-           |= htole32(IWM_STA_FLG_FAT_EN_MSK | IWM_STA_FLG_MIMO_EN_MSK);
+           |= htole32(IWM_STA_FLG_FAT_EN_MSK);
+#ifdef notyet /* FIXME: we are not yet ready for MIMO! */
+       add_sta_cmd.station_flags_msk
+           |= htole32(IWM_STA_FLG_MIMO_EN_MSK);
+#endif
        add_sta_cmd.tid_disable_tx = htole16(0xffff);
        if (update)
                add_sta_cmd.modify_mask |= (IWM_STA_MODIFY_TID_DISABLE_TX);
$
The debug message changes are no longer necessary and can reverted:
$ got revert sys/dev/pci/if_iwm.c
R  sys/dev/pci/if_iwm.c
$ got status
 M sys/dev/pci/if_iwm.c
To commit the staged change, run got commit as usual:
$ got commit -m "disable MIMO for now to work around a crash reported on bugs@"

A second possibility is to revert all debug message changes with got revert:

$ got revert -p sys/dev/pci/if_iwm.c
-----------------------------------------------
@@ -4620,6 +4620,8 @@ iwm_add_sta_cmd(struct iwm_softc *sc, struct iwm_node
        uint32_t status;
        struct ieee80211com *ic = &sc->sc_ic;

+       printf("%s: adding node for STA %s\n", __func__, ether_sprintf(in->in_ni.ni_macaddr));
+
        if (!update && (sc->sc_flags & IWM_FLAG_STA_ACTIVE))
                panic("STA already added");

-----------------------------------------------
M  sys/dev/pci/if_iwm.c (change 1 of 4)
revert this change? [y/n/q] y
-----------------------------------------------
@@ -4638,7 +4640,11 @@ iwm_add_sta_cmd(struct iwm_softc *sc, struct iwm_node
        }
        add_sta_cmd.add_modify = update ? 1 : 0;
        add_sta_cmd.station_flags_msk
-           |= htole32(IWM_STA_FLG_FAT_EN_MSK | IWM_STA_FLG_MIMO_EN_MSK);
+           |= htole32(IWM_STA_FLG_FAT_EN_MSK);
+#ifdef notyet /* FIXME: we are not yet ready for MIMO! */
+       add_sta_cmd.station_flags_msk
+           |= htole32(IWM_STA_FLG_MIMO_EN_MSK);
+#endif
        add_sta_cmd.tid_disable_tx = htole16(0xffff);
        if (update)
                add_sta_cmd.modify_mask |= (IWM_STA_MODIFY_TID_DISABLE_TX);
-----------------------------------------------
M  sys/dev/pci/if_iwm.c (change 2 of 4)
revert this change? [y/n/q] n
-----------------------------------------------
@@ -4675,7 +4681,7 @@ iwm_add_sta_cmd(struct iwm_softc *sc, struct iwm_node
        status = IWM_ADD_STA_SUCCESS;
        err = iwm_send_cmd_pdu_status(sc, IWM_ADD_STA, sizeof(add_sta_cmd),
            &add_sta_cmd, &status);
-       if (err == 0 && status != IWM_ADD_STA_SUCCESS)
+       if (err == 0 && status != IWM_ADD_STA_SUCCESS) {
                err = EIO;
                printf("ADD_STA_CMD failed: add_modify=%d flags=0x%x\n",
                    add_sta_cmd.add_modify, add_sta_cmd.station_flags_msk);
-----------------------------------------------
M  sys/dev/pci/if_iwm.c (change 3 of 4)
revert this change? [y/n/q] y
-----------------------------------------------
@@ -4677,6 +4683,9 @@ iwm_add_sta_cmd(struct iwm_softc *sc, struct iwm_node
            &add_sta_cmd, &status);
        if (err == 0 && status != IWM_ADD_STA_SUCCESS) {
                err = EIO;
+               printf("ADD_STA_CMD failed: add_modify=%d flags=0x%x\n",
+                   add_sta_cmd.add_modify, add_sta_cmd.station_flags_msk);
+       }

        return err;
 }
-----------------------------------------------
M  sys/dev/pci/if_iwm.c (change 4 of 4)
revert this change? [y/n/q] y
$
This leaves us with the workaround as our only local change we can commit:
$ got diff
diff a737ddea9a6b93fdcfad0176dad8d184b2e2138a /usr/src
blob - 335033d21091a23511403804f09d1548b109b104
file + sys/dev/pci/if_iwm.c
--- sys/dev/pci/if_iwm.c
+++ sys/dev/pci/if_iwm.c
@@ -4638,7 +4638,11 @@ iwm_add_sta_cmd(struct iwm_softc *sc, struct iwm_node
        }
        add_sta_cmd.add_modify = update ? 1 : 0;
        add_sta_cmd.station_flags_msk
-           |= htole32(IWM_STA_FLG_FAT_EN_MSK | IWM_STA_FLG_MIMO_EN_MSK);
+           |= htole32(IWM_STA_FLG_FAT_EN_MSK);
+#ifdef notyet /* FIXME: we are not yet ready for MIMO! */
+       add_sta_cmd.station_flags_msk
+           |= htole32(IWM_STA_FLG_MIMO_EN_MSK);
+#endif
        add_sta_cmd.tid_disable_tx = htole16(0xffff);
        if (update)
                add_sta_cmd.modify_mask |= (IWM_STA_MODIFY_TID_DISABLE_TX);
$

Sometimes a mistake is found in the latest commit on a branch. This section explains how such a mistake can be corrected with Got.

As a first step, Got can create another commit which undoes the changes made by the latest commit. Assuming a branch called master, the latest commit on this branch can be identified by the same name (master). In a clean work tree according to got status, run:

$ got backout master
$ got commit -m 'oops, roll back previous change'
Using got backout a second time will now fetch the rolled-back change into the work tree as a local change which can be amended:

$ got backout master
(edit files)
$ got commit -m 'fixed version of previous change'
The history of the tree latest commits on the branch would now look something like this:
$ got log -l 3
-----------------------------------------------
commit bcb49d15e041ddffb59397d2fe851fdb1729b005 (master)
from: Flan Hacker <flan_hacker@openbsd.org>
date: Wed Aug 14 22:07:22 2038 UTC
 
  fixed version of previous change
 
-----------------------------------------------
commit 82f6abb8b1a22fe62d2a8a8d0cdbb73c9d85fcda
from: Flan Hacker <flan_hacker@openbsd.org>
date: Wed Aug 14 21:37:07 2038 UTC
 
  oops, roll back previous change
 
-----------------------------------------------
commit 7ef28ff8dd61cbf38f88784ea8c11e373757985f
from: Flan Hacker <flan_hacker@openbsd.org>
date: Wed Aug 14 21:10:00 2038 UTC
 
 this is surely a great idea!
 

If commit 7ef28ff8dd61cbf38f88784ea8c11e373757985f has already been copied to another repository, our story ends here because the history must now be considered immutable.

Otherwise, the local branch history can be edited to cover up our little mistake. First, find the ID of the parent commit of the bad commit:

$ got log -l 4 | grep ^commit| tail -n 1
commit e27a7222faaa171dcb086ea0b566dc7bebb74a0b (origin/master)

Back-date the work tree to this commit and ask Got to edit the history leading up to the latest commit on the branch:

$ got update -c e27a7222fa
$ got histedit

The histedit command will open a histedit script in an editor:

# Available histedit commands:
#   pick (p): use commit
#   edit (e): use commit but stop for amending
#   fold (f): combine with commit below
#   drop (d): remove commit from history
#   mesg (m): single-line log message for commit above (open editor if empty)
# Commits will be processed in order from top to bottom of this file.
pick 7ef28ff8dd61cbf38f88784ea8c11e373757985f this is surely a great idea!
pick 82f6abb8b1a22fe62d2a8a8d0cdbb73c9d85fcda oops, roll back previous change
pick bcb49d15e041ddffb59397d2fe851fdb1729b005 fixed version of previous change

To make the mistaken commits disappear from history, the corresponding lines can changed to execute drop commands, and the log message of the latest commit can be changed to that of the original commit:

drop 7ef28ff8dd61cbf38f88784ea8c11e373757985f this is surely a great idea!
drop 82f6abb8b1a22fe62d2a8a8d0cdbb73c9d85fcda oops, roll back previous change
pick bcb49d15e041ddffb59397d2fe851fdb1729b005 fixed version of previous change
mesg this is surely a great idea!

After saving the file and exiting the editor, Got will create a new version of history which does not contain the mistake:

$ got log -l 1
-----------------------------------------------
commit 60b83404dd25547f19d9b468b931809541a3325c (master)
from: Flan Hacker <flan_hacker@openbsd.org>
date: Wed Aug 14 22:17:12 2038 UTC
 
  this is surely a great idea!
 

CAVEAT:

The mesg command of the histedit script only accepts a single-line log message argument. Omit the argument to write a new multi-line log message in an editor:

[...]
pick bcb49d15e041ddffb59397d2fe851fdb1729b005 fixed version of previous change
mesg

Clone the ports repository from github. This step currently requires git(1):

$ mkdir /var/git
$ cd /var/git
$ git clone --bare https://github.com/openbsd/ports.git

We jump into ports.git directory and we create our new branch to work with (let's say mystuff):

$ cd ports.git
$ got branch mystuff
We check that the master and the new branch are in sync:

$ got branch -l
master: 05a7abcec81fc1865d1983314b6783680ab31f689
mystuff: 05a7abcec81fc1865d1983314b6783680ab31f689

Now we need to checkout the content inside our new branch mystuff

$ cd /var/git
$ got checkout -b mystuff ports.git
...
A  /var/git/ports/x11/yeahconsole/distinfo
A  /var/git/ports/x11/yeahconsole/patches/patch-Makefile
A  /var/git/ports/x11/yeahconsole/pkg/DESCR
A  /var/git/ports/x11/yeahconsole/pkg/PLIST
A  /var/git/ports/x11/yeahlaunch/Makefile
A  /var/git/ports/x11/yeahlaunch/distinfo
A  /var/git/ports/x11/yeahlaunch/patches/patch-yeahlaunch_c
A  /var/git/ports/x11/yeahlaunch/pkg/DESCR
A  /var/git/ports/x11/yeahlaunch/pkg/PLIST
Now shut up and hack

As got says, now shut up and hack:

$ cd /var/git/ports
$ cd www/nextcloud
$ vim pkg/README

So we changed the README file inside the Nextcloud port and we need to cook the diff:

$ got diff
diff 05a7abcec81fc1865d1983314b6783680ab31f689 /var/git/ports
blob - 47bfbdd7fa7aaf027971ac5c62db25dde75595d7
file + www/nextcloud/pkg/README
--- www/nextcloud/pkg/README
+++ www/nextcloud/pkg/README
@@ -96,12 +96,20 @@ server "domain.tld" {
                block return 301 "$DOCUMENT_URI/index.php"
        }

-       location "/nextcloud/ocm-provider/" {
-               block return 301 "$DOCUMENT_URI/index.php"
+       location "/.well-known/carddav" {
+               block return 301 "https://$SERVER_NAME/nextcloud/remote.php/dav"
        }

-       location "/nextcloud/ocs-provider/" {
-               block return 301 "$DOCUMENT_URI/index.php"
+       location "/.well-known/caldav" {
+               block return 301 "https://$SERVER_NAME/nextcloud/remote.php/dav"
+       }
+
+       location "/.well-known/webfinger" {
+               block return 301 "https://$SERVER_NAME/nextcloud/public.php?service=webfinger"
+       }
+
+       location match "/nextcloud/oc[ms]%-provider/*" {
+               directory index index.php
        }
 }
 ---8<---------------------------------------------------------------------------

Time to commit those changes in our branch mystuff, so we can keep track of our work:

$ got commit -m "Add new examples for httpd(8) to shut up warnings"
M  www/nextcloud/pkg/README
Created commit 7848652ef6243db09841d449f346f21fc6386633

Paranoid? Probably yes, let's check again our diff against master:

$ got diff master mystuff
diff refs/heads/master refs/heads/mystuff
blob - 47bfbdd7fa7aaf027971ac5c62db25dde75595d7
blob + 71d2df1463ae11c9b66403d401c16fff63382b2c
--- www/nextcloud/pkg/README
+++ www/nextcloud/pkg/README
@@ -96,12 +96,20 @@ server "domain.tld" {
                block return 301 "$DOCUMENT_URI/index.php"
        }

-       location "/nextcloud/ocm-provider/" {
-               block return 301 "$DOCUMENT_URI/index.php"
+       location "/.well-known/carddav" {
+               block return 301 "https://$SERVER_NAME/nextcloud/remote.php/dav"
        }

-       location "/nextcloud/ocs-provider/" {
-               block return 301 "$DOCUMENT_URI/index.php"
+       location "/.well-known/caldav" {
+               block return 301 "https://$SERVER_NAME/nextcloud/remote.php/dav"
+       }
+
+       location "/.well-known/webfinger" {
+               block return 301 "https://$SERVER_NAME/nextcloud/public.php?service=webfinger"
+       }
+
+       location match "/nextcloud/oc[ms]%-provider/*" {
+               directory index index.php
        }
 }
 ---8<---------------------------------------------------------------------------

Now, let's send that diff to ports@ for some OKs.

Once the diff has been committed to CVS the same change will eventually show up on github as well. Fetch incoming changes to the master branch with:

$ cd /var/git/ports.git
$ git fetch origin master:master

Next, rebase the mystuff branch onto the latest master:

$ cd /var/git/ports
$ got status
(status should be clean; revert or commit local changes if needed)
$ got update -b master
$ got rebase mystuff

Now we can shut up and hack again!