Git workflow¶
Short introduction to Git and the related workflow¶
Git can be intimidating and being familiar with it takes some getting use to. There are numerous resources on the internet, like the Dangit, Git!?! or Git documentation, Git from the bottom up, Things I wish everyone knew about Git.
Here is a short, opinionated, by no means comprehensive guide to the typical steps that are needed when working with Gadgetbridge code and repo. Use this as a simple guide but do make sure to read-up on git more in other places, in documentation and so on. If you spot an issue, please edit it too, to help other to be more confident and comfortable when using git.
Forking the repository¶
Initial step: fork the Gadgetbridge repo on Codeberg to have your own repo. You do this by using the Fork button on the Gadgetbridge repo page. This will create your copy of the repo in Codeberg, under your username. The username will be unique to you, so in this steps, username indicates a Codeberg and you must replace it with your username if you copy/paste these commands. As this copy is sitting on the remote Codeberg server, we will refer to it as a remote or as origin. In order to work with the code, you will need to make a local copy via cloning.
Cloning your forked copy¶
To get the code to your computer, you must clone the repo.
This will create local copy of the repository. The remote copy will be named origin, while the official Gadgetbridge repository is registered in your cloned repo as upstream.
Master branch¶
The main branch of the Gadgetbridge repo is called master.
Creating a branch¶
When adding a feature for later merge/pull request, you typically create a branch. You do a branch and do not do this in the master, because you will typically like to keep the master as is, in order to be able to have it to follow the upstream's master in Gadgetbridge repo. You can either add a branch before you start.
Or you can first make some changes, and only then make the branch, for example like this:
- Do some edits.
git add ./path_to_the_changed file(s)git checkout -b new-branch
Committing into the branch¶
Your changes are now being stored into your my-new-branch by committing:
Pushing your local branch to your remote on the server¶
Switching branches¶
As long as all your changes are committed, you can switch between different branches, like this:
git checkout master in order to perhaps see how things are in the master branch and then you can go back to your new-branch git checkout new-branch.
Seeing changes between branches¶
You can see diffs between your new-branch and the master:
You can also get the master version of a file you edited, to roll it back to the "original" state:
Syncing with the Gadgetbridge project¶
This is all cool, but while you work on your thing, the Gadgetbridge project is moving along and you must stay synced to it. You do this by switching to the master branch and pulling the remote changes:
This updates your local master to be the same as upstream.
Rebasing on top of the master¶
You must also ensure, that your branch is actually based on the master. You do this by rebasing on top of the master:
- Switch to the master and make sure it is up to date with upstream:
git pull upstream master - Switch back to your branch:
git checkout my-branch - Then "rebase" it on top of the remote master:
git rebase upstream/master
Resetting the master to the upstream¶
Sometimes, you mess things up badly and want to make sure that your local master is really the same as the upstream master. This can be done by using the destructive reset command of git. This will cause local data loss, so be sure to know why you do this.
- You switch to your master:
git checkout master - Remove all unadded files:
git clean -f -d - And then reset it to upstream:
git reset --hard upstream/master --
Squashing commits via git rebase¶
The git rebase command is very power full and allows you to do many things, like remove, re-order or squash commits, edit the commit message and so on. Read-up about it in the documentation. One of the things it can do is to allow you to selectively squash commits. This can be done in an interactive way by using the -i option and choosing a commit where you want to start. As the action of using the rebase still makes a commit, so somewhat counter intuitively you must choose "one commit before the start" of your commits:
In the text editor that is opened for you, you leave the first line intact and edit the pick word in front of the commits on the following lines. For example by changing the pick to squash (or to s), this commit will be squashed to the one above it. As mentioned, leave the first line intact. Save and close the file, which will invoke the squashing.
Force pushing¶
As the above-mentioned rebase actions overwrite git history, if you have previously pushed to your remote, you must force push now. You should not do this if this is for example a master branch and you share the repo with other people, because this breaks things for them (again, read-up about it). But for your work and/or while working alone in a dedicated branch, this is OK. You will also do this quite a bit if this branch is used as a pull/merge request.
Testing a pull request¶
When people submit a pull request (PR), you can clone it and test it quite easily:
This will clone a PR number 1234 into a local branch called branch_name. Now the branch is local and you can work with it like with any other branch.
Save a snapshot without creating a commit in your working branch¶
Do a git stash, followed by a git stash apply. This will create a named commit which can be accessed or checked out at any time back. List all stashed with git stash list.
An undo for git¶
As long as you added and committed your files and did not accidentally erased the .git folder, you can mostly recover all your commits even if you for example squashed or removed them or removed a complete branch. Use git reflog, (short for "reference logs") to get a list of previous commits and changes. Here you can note the commit hashes and get them back for example by cherry-picking: