-
Notifications
You must be signed in to change notification settings - Fork 78
FujiNet Development Guidelines
FujiNet is a fun project with many repositories and developers. However, that can at times lead to a turbulent git history, and lead to difficulties later down the line when someone needs to bisect the repository to find when a particular change affected some element of the project.
The following is an attempt to give people some simple instructions on how to develop in a consistent manner with git, which will lead to cleaner history, and an easier time for everyone on the project viewing and understanding changes.
Throughout this guide, I will use the fujinet-apps repo as an example, but it applies to any other repo in the project.
You should first fork the repository on github through your personal account, then clone it locally:
git clone [email protected]:markjfisher/fujinet-apps.gitThis will allow you to easily fetch changes from other developers, and combine them with any changes you are also in the process of making.
You should only do one of the following:
# If you are going to create Pull Requests in GitHub (the norm for most developers)
git remote add upstream https://github.com/FujiNetWIFI/fujinet-apps.git
# If you have direct push access, then use:
git remote add upstream [email protected]:FujiNetWIFI/fujinet-apps.git$ git fetch upstream master
$ git merge upstream/master --ff-only
Updating a853c6a7..dc641090
Fast-forward
apod/CHANGES.txt | 3 +++
... other changes here
9 files changed, 85 insertions(+), 16 deletions(-)The above should be done at the start of all new development, so you are working off the latest changes in master.
If you pulled any changes down (maybe your repo hasn't been updated in a while), you can now push these latest changes to your own fork:
git push
Let's say I'm adding a new example application called "ipify" to the apps repo. It's going to be cross-platform, so I'm going to call the branch xp-ipify and commit my work into the branch.
$ git checkout -b xp-ipify
Switched to a new branch 'xp-ipify'I'm now ready to make my changes, adding files and creating local commits as I need. Finally I want to push my work up to github, and get it into the main codebase.
We first want to ensure we've only created a single commit, if possible, to represent the change. Changes work best if they are small and specific to some higher goal. In this example, I created 5 commits for all the changes, including "WIP" work in progress, and some fixes, etc.
(Note, I've deliberately made commits with terrible commit messages here! See later on in the document for a section about Git Commit Messages, and how to properly format them. If you find yourself using "oops", "WIP", or other short commits in hurry, read the section on git commit messages a few times, and start formatting them correctly! e.g. instead of "oops", use "Fix compiler issue in atari network lib". This will help you when squashing commits and trying to work out a decent short commit subject to use.)
So anyway, we don't want to expose all those changes to everyone else, and we're going to first "squash" the changes into a single commit using git's "rebase" functionality.
(If in your case, you only created 1 commit with a decent subject, then excellent, you can skip down to the section Preparing to push your changes back to GitHub below.)
$ git log --pretty=format:"%h %ad | %s%d [%an]" --graph --date=short -10
* c76e4daa 2023-12-30 | Working ipify (HEAD -> xp-ipify) [Mark Fisher]
* 95e52497 2023-12-30 | oops [Mark Fisher]
* 79b7d432 2023-12-30 | WIP - makefile changes [Mark Fisher]
* 3f89ff22 2023-12-30 | Initial Makefile [Mark Fisher]
* 8c919098 2023-12-30 | Added README [Mark Fisher]
* ... other changes from before we startedWe have 5 commits, and to "squash" them into a single commit we issue an "interactive rebase" git command:
git rebase -i HEAD~5Note the number at the end is because we're going to squash 5 commits in this example, and must come after the ~ character.
Change this to the number of commits you are squashing into one.
You will then see a git window for squashing the commits. There is information on what to do in comments in the page it shows. For example:
pick 8c919098 Added README
pick 3f89ff22 Initial Makefile
pick 79b7d432 WIP - makefile changes
pick 95e52497 oops
pick c76e4daa Working ipify
# Rebase dc641090..c76e4daa onto dc641090 (5 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# ... other information
First notice the 5 commits are in reverse order, the oldest being at the top. Down the left side is currently the word "pick", we need to change all but the first into a "squash".
So, edit the file to look like the following (you can ignore the comment and blank lines):
pick 8c919098 Added README
squash 3f89ff22 Initial Makefile
squash 79b7d432 WIP - makefile changes
squash 95e52497 oops
squash c76e4daa Working ipify
It's always "leave the first as pick, change everything else to squash". You can use just the letter "s" instead of "squash" if you're feeling particularly lazy.
Save the file, and git will work its magic, and then ask you to change the commit message of the overall single commit you're creating.
# This is a combination of 5 commits.
# This is the 1st commit message:
Added README
# This is the commit message #2:
Initial Makefile
# This is the commit message #3:
WIP - makefile changes
# This is the commit message #4:
oops
# This is the commit message #5:
Working ipify
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
You can now craft your final commit message for the single change you're making, e.g.
Add cross-platform ipify app to test network-lib json functions
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
Save and exit your editor, and it will show git's output for the operation.
...
[detached HEAD a10c5625] Add cross-platform ipify app to test network-lib json functions
Date: Sat Dec 30 18:02:29 2023 +0000
4 files changed, 4 insertions(+)
create mode 100644 ipify/Makefile
create mode 100644 ipify/README.md
create mode 100644 ipify/ipify.c
create mode 100644 ipify/ipify.h
Successfully rebased and updated refs/heads/xp-ipify.
Doing another git history will show you now have 1 commit.
$ git log --pretty=format:"%h %ad | %s%d [%an]" --graph --date=short -10
* a10c5625 2023-12-30 | Add cross-platform ipify app to test network-lib json functions (HEAD -> xp-ipify) [Mark Fisher]
* ... other commits from older work hereWhen you're finally happy with your changes, and have crafted the single commit, you will want to push it back to GitHub.
However, someone else may have already made changes since we started our own work, so we will want to put our changes on top of those before we push our changes back.
This is an important step.
Part of keeping a clean history, and to ensure your changes are not going to conflict with other developers changes, means doing a check to see if anyone else has made a change before you push.
$ git checkout master
$ git fetch upstream master
$ git merge upstream/master --ff-only
$ git checkout xp-ipify
$ git rebase masterIf successful, you have put your changes on top of the latest changes.
If git reports an error in the last stage, you will have a merge-conflict. Something in your change conflicted with changes someone else made. You will need to fix the changes, add them to your commit, and finish the rebase.
This is slightly more advanced than this page will go into, and should not happen unless you're making sweeping changes, which would probably mean you already know what you're doing. If not, and you do get a conflict, a quick google search for "git merge conflict" will guide you through what is needed, but it essentially boils down to fixing the issue in your editor, adding the changes to git, then continuing the rebase until git is happy it was able to take the changes. Your IDE of choice usually has ways to help here.
As you get used to git workflows, you will quickly recognise when there are no upstream changes, and so you will not need to rebase your changes, as there's nothing to put them on top of. However, the above is a good working example of how to switch branches, pull changes, then switch back to your own branch and move your work on top of the latest remote changes.
If you're working on your own fork, and do not have direct push access to the main repository (the norm for most developers), you can push your changes to your fork, and then create a Merge Request in github.
Start by pushing your changes:
# If this is the first time you've pushed your branch to github, use the following to tell it the branch name:
$ git push --set-upstream origin xp-ipify
Enumerating objects: 8, done.
Counting objects: 100% (8/8), done.
Delta compression using up to 24 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (7/7), 534 bytes | 267.00 KiB/s, done.
Total 7 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
remote:
remote: Create a pull request for 'xp-ipify' on GitHub by visiting:
remote: https://github.com/markjfisher/fujinet-apps/pull/new/xp-ipify
remote:
To github.com:markjfisher/fujinet-apps.git
* [new branch] xp-ipify -> xp-ipify
branch 'xp-ipify' set up to track 'origin/xp-ipify'.Note, you only have to use the --set-upstream origin xp-ipify part once when you first push your new branch to github. After that, you can just use git push if you're pushing multiple changes to the remote. But it's best to aim for only pushing to github once if possible, unless you're asked to do some rework on your changes.
As you can see from the output, github has shown you how you can make a Pull Request, by clicking on the link.
Click the link, and edit the details of the page, and generate a Pull Request. You can mention your work in Discord, and someone will be along to look at your change and check it's in a good shape to merge into the main repo.
Congratulations, you just merged code into the main repository!
Afterwards, you can clean up your branch, by deleting it if you no longer need it.
When the code has been merged, you can go back to the start of this document, and pull the latest changes from upstream to see your changes in the main code line.
If you have appropriate access, you can directly push your changes to the upstream repository.
To do this, if you were developing on a branch, then first rebase your branch onto master
git checkout master # change to master
git merge xp-ipify --ff-only # fetch the changes from your branch
git push # push changes to master branch of your own fork
git push upstream # push changes to main repoNote: It is vital you use --ff-only to ensure you do not create a merge request, and that all you are doing is changing your master branch pointer to the same place as your branch's HEAD. You can alternatively simply do git rebase xp-ipify in this example for the 2nd line, but doing merge with --ff-only doubly ensures you are not going to create merge commits.
As you should have already pulled the latest changes from master and rebased your code (as described in the previous sections), the reverse of pulling your changes into master should just be a matter of moving the master branch pointer to the same commit, and not actually having to do a merge.
There is considerable debate over what makes a good commit message. In the previous examples I deliberately gave some bad ones (like "oops" and "WIP") before squashing them into a single commit with a better message.
Many companies have started using commit messages to contain additional information that helps the build process generate automated change logs, and do automatic version bumping based on the message itself. That's way too much for a project like this one, and requires considerable discipline.
Instead, we should be strive for a few simple goals when writing commit messages, detailed below.
A good read that already covers a lot of this can be found at https://gist.github.com/robertpainsi/b632364184e70900af4ab688decf6f53
The git commit has a specific format. There's a subject line, (which should be kept as short as possible), followed by a blank line to separate the title from the body of the commit message, then the body of the commit message itself, if required.
In most situations, the subject line should be enough, but if you need to add more detail then move it into the body section.
Add ipify app to test network-lib
ipify is a simple cross-platform application that exercises the network-lib
functionality.
Here you can see a short title, the blank line, and the body explanation.
The blank line is actually important, git itself requires it to separate the title from the body, and without it, your body will appear in the summary on the same line as the title, so it's not good enough to start the body text on the line after the subject, there has to be a full blank line.
The git subject line should be able to fulfil the following statement:
If applied, this commit will <your subject line here>
So instead of past tense (e.g. "Added foo to bar"), it should be imperative, or present tense ("Add foo to bar").
Read back the above statement in your head for both examples ("If applied, this commit will..."), and you'll see why Add is better than Added.
As mentioned previously the body should be a full blank line after the title. It can contain additional information that will help maintainers and other developers understand what the change is doing if the subject line isn't enough.
It's very rare that I use this feature, but it can be useful if you want to include things like Issue Numbers in Github, for example
Add ipify app to test json network-lib
This completes issue #1234
where 1234 is the GitHub issue number the change is related to, if you're working on fixing a reported bug for example.
This isn't a place to wax lyrical about your change either. Tests are usually the best way to document your change, but that isn't something we have the luxury of at the moment in this project.
So keep your body short, you can mention platforms here, mention issue numbers, but things like "Used a loop to count the foo so it would be faster to process the bar" does not make for a good body.
A quick way to do this to just your most recent commit you have locally that hasn't been pushed to a remote server is to use:
git commit --amend
This will present you with an editor that you can use to change the title, and even add or change the body. Save that file and exit your editor, and git will update the commit with the new message.
NOTE: you should strive to never amend commits after you have sent them upstream. This is because you are rewriting history. Even just the commit message itself, you are generating a brand new commit (it has a different ID to the previous one), and everyone else will have your old commit.
If you want to change the commit message of a change from several commits ago (again, that you have not pushed upstream), then if you look back at the "commands" available when doing the interactive rebase earlier, one of them is "reword". You can use this to change just the git commit message of a particular commit. In that case, keep everything as "pick" except the commit you want to change the message for, and change that to "reword". Save the "commands", and git will then offer you a chance to edit your message on the commit you wanted to change.
I have never done this. This is because instead, I will squash all commits into a single commit, and so I don't need to change the commit message of something several commits ago. And I would never do this to commits from other people, as you cannot amend commits that have come from the upstream repo, without breaking everyone elses git repo.
I have the following I add to every git config I have on every machine I'm ever working on. They simplify doing certain git commands:
This section goes in the file ~/.gitconfig
[alias]
st = status
hist = !sh -c 'git log --pretty=format:\"%h %ad | %s%d [%an]\" --graph --date=short -${1:-20} ${2:-HEAD}' -
amend = !git log -n 1 --pretty=tformat:%s%n%n%b | git commit -F - --amend
ls = log --pretty=format:"%C(yellow)%h%Cred%d\\ %Creset%s%Cblue\\ [%cn]" --decorate
ll = log --pretty=format:"%C(yellow)%h%Cred%d\\ %Creset%s%Cblue\\ [%cn]" --decorate --numstat
dr = "!f() { git diff "$1"^.."$1" ${2:-}; }; f"
lc = "!f() { git ll "$1"^.."$1" ${2:-}; }; f"
Here's some examples of using them:
Use git hist. Without a parameter it will default to 20 lines. With a parameter, it will limit it to less. Also allows targeting other git refs. See git docs to understand that, the simplest version is:
$ git hist 5
* eeee68bb 2023-12-30 | Add ipify app to test network-lib json functions (HEAD -> master) [Mark Fisher]
* dc641090 2023-12-29 | Talk to my site via HTTPS; new version bump (tag: apod-2023-12-29, upstream/master, origin/master, origin/HEAD) [Bill Kendrick]
* 257d5683 2023-12-29 | Merge branch 'master' of https://github.com/FujiNetWIFI/fujinet-apps [Bill Kendrick]
|\
| * a241e9ac 2023-12-28 | Merge commit 'a853c6a7a0eb343c355428dbe40218498744558b' [idolpx]
| |\
| | * a853c6a7 2023-12-26 | clean up jsontest crossplatform makefile [Mark Fisher]You can use git ls with or without a parameter for the number of lines to show. Without, it will show everything.
$ git ls -5
eeee68bb (HEAD -> master) Add ipify app to test network-lib json functions [Mark Fisher]
dc641090 (tag: apod-2023-12-29, upstream/master, origin/master, origin/HEAD) Talk to my site via HTTPS; new version bump [Bill Kendrick]
257d5683 Merge branch 'master' of https://github.com/FujiNetWIFI/fujinet-apps [Bill Kendrick]
a241e9ac Merge commit 'a853c6a7a0eb343c355428dbe40218498744558b' [idolpx]
4913aae7 don't translate underscore to petscii glyph [idolpx]
git ll is similar, but also shows the change summary within the commits:
$ git ll -2
eeee68bb (HEAD -> master) Add ipify app to test network-lib json functions [Mark Fisher]
1 0 ipify/Makefile
1 0 ipify/README.md
1 0 ipify/ipify.c
1 0 ipify/ipify.h
dc641090 (tag: apod-2023-12-29, upstream/master, origin/master, origin/HEAD) Talk to my site via HTTPS; new version bump [Bill Kendrick]
3 0 apod/CHANGES.txt
11 11 apod/fetch.c
3 2 apod/screen_helpers.c
2 2 apod/version.h
Use git dr <ref> to see what that commit contains:
$ git dr dc641090
diff --git a/apod/CHANGES.txt b/apod/CHANGES.txt
index 863160ab..714f2d16 100644
--- a/apod/CHANGES.txt
+++ b/apod/CHANGES.txt
@@ -1,6 +1,9 @@
apod (Astronomy Picture of the Day) Client for #FujiNet
Change Log
+ * 2023-12-29
+ + Talking to my websever over HTTPS now.
+
* 2021-06-10
+ Split colorbars into a test version of the APOD app,
so the main app has a little more breathing room.
... etc.
Note you can get the ref from the first part of git hist, it is the short commit id hash.
You can also use "HEAD" or any other valid git reference.
The command git commit --amend can be used to update your latest commit message (THAT YOU HAVE NOT PUSHED TO GITHUB!!) as previously mentioned.
However it is more usual to use it to add new file changes into your current commit without creating a new commit on top, so you only have 1 git commit you're constantly updating with your changes.
Here's an example session
# ... we edit some files, and commit them
$ git add -A
$ git commit -m 'Add ipify app'
# then you notice there was a typo, or you want to change some functionality
# so you edit the files, then at the end:
$ git add -A # this adds your changes to git
$ git amend # this uses the aliasThis will apply git commit --amend but use the same commit message you previously typed, skipping the message dialog completely.
There is an important thing to realise here: you are forever changing your previous commit, so you cannot get back to the previous version easily if your "amend" needs to be rolled back, it can't. Usually this isn't a problem, you forgot a small part, and want to just update the current commit you made rather than having 2 commits you later squash. Simply 'amend' the current commit with the new changes. This alias helps you do that without the annoying commit message dialog.
Copyright 2024 Contributors to the FujiNetWIFI project.
Join us on Discord: https://discord.gg/7MfFTvD
- Home
- What is FujiNet?
- The Definition of Done
- Board bring up for FujiNet Platform.IO code
- The Complete Linux CLI Guide
- The Complete macOS CLI Guide
- Development Env for Apps
- FujiNet-Development-Guidelines
- System Quickstarts
- FujiNet Flasher
- Setting up a TNFS Server
- FujiNet Configuration File: fnconfig.ini
- AppKey Registry - SIO Command $DC Open App Key
- CP-M Support
- BBS
- Official Hardware Versions
- Prototype Board Revisions
- FujiNet Development Guidelines
- Atari Programming
- Apple Programming
- C64 Programming
- ADAM Programming
- Testing Plan
- Hacker List
- FujiNet VirtualMachine