Git History Examples - FujiNetWIFI/fujinet-firmware GitHub Wiki

This page assumes you've setup a git alias for git history as detailed in the Git Config Aliases page.

It is preferable to have a clean history in git with as few merge commits as possible.

This makes it much easier to follow the history of changes, and also move around the timeline of changes, and see where changes were introduced.

Single history - holy grail

The following is an example of the holy grail of commit histories, a single timeline with no merges.

$ git hist
* 38deb08a 2023-12-25 | 2023 Day 24 P2 with z3 library (HEAD -> master) [Mark Fisher]
* 67a61a17 2023-12-25 | 2023 Day 24 and 25 Merry Xmas [Mark Fisher]
* 2e93557c 2023-12-24 | 2023 Day 23 P1 hailstones [Mark Fisher]
* 70a3b34f 2023-12-23 | 2023 Day 23 P1 Icy Paths - NP problem [Mark Fisher]
* f99c246d 2023-12-22 | 2023 Day 22 Rewrite as simulation was taking forever [Mark Fisher]
* 3ebecbfa 2023-12-22 | 2023 Day 22 WIP part 1 falling sand blocks [Mark Fisher]
* 18e46e5c 2023-12-21 | 2023 Day 21 Infinite garden (origin/master, origin/HEAD) [Mark Fisher]
* 06d8e229 2023-12-20 | 2023 Day 20 Part 2 - LCM again [Mark Fisher]
* 329f5222 2023-12-20 | 2023 Day 20 P1 pulses [Mark Fisher]
* 12dc74f2 2023-12-19 | 2023 Day 19 Part 2 - Apply logic to bound ranges [Mark Fisher]
* 82956f6c 2023-12-19 | 2023 Day 19 P1 - Workflows/Rules/Parts [Mark Fisher]
* 7664b20e 2023-12-18 | 2023 Day 18 Areas and coverings - shoelace/picks [Mark Fisher]
* 6ad6d32e 2023-12-17 | 2023 Day 17 Part 2 - paths between 4 and 10 [Mark Fisher]
* 93e65a81 2023-12-17 | 2023 Day 16 and Day 17 P1 [Mark Fisher]
* ec5a83cb 2023-12-15 | 2023 Day 15 HASHing around [Mark Fisher]

Every commit is derived from the previous commit, so all the * are uniformly under each other. A developer can easily see what is in each commit, and does not have to refer to any merges, and try and compare the different lines of history to work out what change is actually being made.

I'm cheating here slightly, as it's taken from my own "Advent Of Code" repository, of which I'm the only developer, so there's simply no need for merges at any time. Every commit is just on top of the previous one, so it's kept simple, and clean, without any branches, or merges.

However, in a multi-developer scenario, it's very difficult to keep this discipline.

Many developers have never had to work with git before and may simply be unaware that there are better ways to work with git.

This is the reason I started the Fujinet Development Guidelines so developers are given a set of simple instructions on how to better prepare their changes in a multi-developer project.

Pull Requests from GitHub

Unfortunately, because of how github works, it's impossible to completely remove merge commits, and they will happen as a result of the PR process.

An example of a good simple PR merge is:

*     1097bb98 2023-10-24 | Merge pull request #680 from mike-wiese/master [Thomas Cherryhomes]
|\    
| *   e61487e9 2023-10-23 | fix web mount list on apple2 [Mike Wiese]
|/    
*     9b60b41c 2023-10-22 | Merge pull request #679 from mike-wiese/improved-floppy-disk-image-support [Thomas Cherryhomes]
|\    
| *   0912d978 2023-10-22 | Add .DO support. Look inside .DSK files to detect sector order. [Mike Wiese]
|/    
*   65adf25d 2023-10-21 | apple: update autorun.po [mozzwald]

Here, 2 changes were made:

  • 0912d978 was based on the previous commit 65adf25d, and was merged into the main tree with GitHub's "Merge pull request #679"
  • e61487e9 was based on the merged commit to main branch (9b60b41c), and a new PR was made and merged with commit 1097bb98

This is a clean example of an external change from a developer using a Pull Request to make changes, and the history kept clean.

An example of a bad complicated history

Using git hist again on the platformio project will show the kind of thing that happens in a repository where developers have not been pulling changes down and rebasing regularly.

This is a section of the commit history where many changes were being made independently of each other

* | | | | 49d11aa7 2023-07-05 | main: replace fnSPIFFS with fsFlash for all platforms 
| * | | | 9c355b12 2023-07-05 | Merge branch 'master' into release 
| |\| | | 
| | * | |   a0ad8305 2023-07-05 | Merge branch 'FujiNetWIFI:master' into master 
| | |\ \ \  
| |_|/ / /  
|/| | | |   
* | | | | e5413bb5 2023-07-05 | finish littlefs support 
* | | | |   6f6ec91d 2023-07-05 | Merge branch 'master' of https://github.com/FujiNetWIFI/fujinet-platformio 
|\ \ \ \ \  
| * \ \ \ \   0aef9323 2023-07-04 | Merge pull request #627 from michaelsternberg/master 
| |\ \ \ \ \  
| | * \ \ \ \   399b96f9 2023-07-04 | Merge branch 'FujiNetWIFI:master' into master 
| | |\ \ \ \ \  
| | |/ / / / /  
| |/| | | | |   
| | * | | | |   df87aa37 2023-07-03 | Merge remote-tracking branch 'refs/remotes/origin/master' 
| | |\ \ \ \ \  
| | * | | | | | b561e9ca 2023-07-03 | Improved EOL translation from ATARI 0x9B --> CR and 0x9B --> LF 
* | | | | | | | 91563fc0 2023-07-04 | Merge branch 'master' of https://github.com/FujiNetWIFI/fujinet-platformio 
|\| | | | | | | 
* | | | | | | | bfdc5b85 2023-07-04 | [iec][disk] don't do open on unlisten
| | | | * | | | 25096268 2023-07-05 | workflow: rename firmware file 
| | | | * | | | 5a7b455d 2023-07-05 | workflow: add path for action-gh-release 
| | | | * | | | 9f222864 2023-07-05 | workflow: don't generate tag 
| | | | * | | | 38ebc351 2023-07-05 | workflow: tag only, fix file path 
| | | | * | | | 4f1d2ca1 2023-07-05 | workflow: get tag from github 
| | | | * | | | 61b37ab0 2023-07-05 | workflow: test manual tagged release 
| | | | * | | | e78c81c6 2023-07-05 | workflow: trying to fix tags/artifact push 
| | | | * | | | 21b3a6c5 2023-07-04 | workflow: trying to create the tag still 
| | | | * | | | 1064594f 2023-07-04 | workflow: testing release tag again 
| | | | * | | | 444bfe35 2023-07-04 | workflow: testing create tag 
| | | | * | | | d815b90f 2023-07-04 | workflow: fix cut syntax 
| | | | * | | | cd1f448d 2023-07-04 | workflow: testing release ver syntax 
| | | | * | | | a9077a6f 2023-07-04 | workflow: fix syntax for get version 
| | | | * | | | 2caa49b8 2023-07-04 | Merge branch 'master' into release 
| | | | |\| | | 
| | | | | * | |   c4f3e415 2023-07-04 | Merge branch 'FujiNetWIFI:master' into master 
| | | | | |\ \ \  
| | |_|_|_|/ / /  
| |/| | | | | |   
| * | | | | | | e5618b24 2023-07-04 | Merge pull request #626 from FozzTexx/master 
|/| | | | | | | 
| * | | | | | | d86cb009 2023-07-04 | Send all bytes read from stream, don't skip final byte. 
| * | | | | | | 6674c4ea 2023-07-04 | ATN getting asserted immediately after EOI byte is not an error, don't abort. Also don't release DATA if ATN is already asserted, DATA has been asserted by ATN interrupt. 
* | | | | | | |   07842a45 2023-07-04 | Merge branch 'master' of https://github.com/FujiNetWIFI/fujinet-platformio 
|\ \ \ \ \ \ \ \  
| | |_|/ / / / /  
| |/| | | | | |   
* | | | | | | | 8c675219 2023-07-04 | add littlefs class 
| | | | * | | | 833a96cf 2023-07-04 | workflow: add tag for release 
| | | | |/ / /  
| | | | * | | 49920d13 2023-07-04 | workflow: fix get ver num 
| | | | * | | 13143cdd 2023-07-04 | workflow: testing new release 
| | | | * | | ee5cc561 2023-07-04 | workflow: build filesystem before firmware 
| | | | * | | a1ed833e 2023-07-04 | pack firmware: run after firmware.bin avail 

In this section there are 13 merge commits pulling parts together.

There are at a lot of places in this history where 8 different pieces of work independent of each other are unmerged and untested together.

This is a bit messy, and adds complexity to understanding how changes have happened.

Every "|" represents a line of commits from some previous unmerged commit, many of them diverge, some of them come back together.

It also shows that changes are made and have never been pulled together until the merge commit happens, usually on the server, so isn't happening on the developers machine, and that means the combination of code is probably not being tested well. This further adds to the difficulty of finding bugs later down the line. Which branch do we go down to get back to a build where we want to check if a feature was working at that point? The complexity quickly escalates, and as someone who has wasted hours of their life having to unpick changes like this to hunt a bug down, I can genuinely say, it isn't fun!

How did we get here?

Quite often it's as simple as the developer not pulling remote changes down before they start their work. They start making commits on top of what is now an "old" commit.

Another issue is not rebasing their changes (and then testing their change still works locally!) before pushing them up to the shared repository.

Both of the above are documented in the best practices page, and how to handle them so that we don't get complicated histories in our git repository.

Doing the 2 simple things of pulling latest changes and rebasing your work on top of latest changes when you are ready to push will remove the merge commits completely from history and move to a much cleaner history, where people can easily track changes, and find when bugs were introduced into the codebase.

It's getting better

The recent changes to platformio have been a lot better, as I type this the history is:

* 2c1f2e71 2023-12-23 | atari: keys: re-enable LED blink for button A press (HEAD -> fen-a2-network-readblock, upstream/master, origin/master, origin/HEAD, master) [mozzwald]
* 68254ed5 2023-12-20 | [coco] autorun.dsk push [Thomas]
* 631faca9 2023-12-20 | [coco] update autorun. [Thomas]
* 276a1695 2023-12-20 | [coco] disk_image_mount() [Thomas]
* 071e1fd3 2023-12-20 | [coco][fuji] get device filename [Thomas]
* 212fec08 2023-12-19 | [coco] updated to test lowercase. [Thomas]
* 42d0e4f1 2023-12-19 | [coco] latest push with dsk [Thomas]
*   88d3d3f6 2023-12-19 | Merge pull request #691 from fredlcore/master [Thomas Cherryhomes]
|\  
| *   ce7e4ec3 2023-12-20 | Merge branch 'master' of https://github.com/FujiNetWIFI/fujinet-platformio [fredlcore]
| |\  
| |/  
|/|   
* | 305a56f3 2023-12-19 | fix setssid and more utf8 modifications [idolpx]
* | 2922203f 2023-12-17 | [coco] working through coco bringup. [Thomas]
* |   c9a6af25 2023-12-17 | Merge branch 'master' of https://github.com/FujiNetWIFI/fujinet-platformio [idolpx]
|\ \  
| * | 6f4c758c 2023-12-16 | [coco] working on select_file [Thomas]
| * | af5c25aa 2023-12-16 | [coco] current config. [Thomas]
| * | d5fc8f8f 2023-12-16 | [coco] device slots code [Thomas]
* | | e4dfa448 2023-12-17 | merging more updates to the iec code [idolpx]
| | * 44128875 2023-12-20 | PINMAP_CX16 instead of PINMAP_ATARI [fredlcore]
| |/  
| * d430881d 2023-12-15 | [coco] wifi hell. [Thomas]
| * c2f480f6 2023-12-15 | [coco] net scan [Thomas]
| * d4c85d49 2023-12-14 | [coco] remove fnconfig.ini [Thomas]

Only a couple of places where merges were needed because the work wasn't rebased, so overall much better.

The culprit commits are c9a6af25, which was needed because e4dfa448 was not rebased from a recent change. It should have been rebased on 6f4c758c, as that was available at the time the changes were pushed back to the upstream repository, which would have negated the need for the merge.

Similarly, 44128875 should have been rebased from 305a56f3, but instead, ce7e4ec3 was first created to merge the changes with current master, then the PR merge also happened, so we have 2 merges instead of 1. This isn't the worst practice, locally a merge was made, but instead a rebase of the changes would have been better to keep the commit history a little cleaner.