How I use git
I use git
every day for nearly everything that I am doing that creates files that change and benefit from either a change history or an archival storage. These are the main guidelines I follow when using it, especially for software projects. Everything I advocate here is just the way I do it because that’s how I have done for a long while. It might not be the best way to accomplish the tasks. It might not fit the way you work with version control. However, three-plus decades of using git
and other source control management systems has directed me to using it in these ways.
Commands
There is a large set of possible commands in the git
set. You can list them all with the help commands:
git help
git help --all
The commands that I use most often are, roughly ordered by the frequency of use:
git commit
git status
git pull
git push
git rebase
git merge
git fetch --all
git branch
git switch
git reset
git log
git reflog
git init
Several of these are used by way of alias definitons or wrapped in a set of helper scripts that I have grown over the years. For example, I rarely use git log
raw like that. It will be used when it use git tree
where tree
is an alias I have defined that shows a pretty log with a nifty history graph.
Workflows
I generally work in a style of Trunk-based Development where main
is kept current as frequently as possible (daily or more) and any branches created are only used for a very short time (daily at most) while working on a new bit of code. Some would not consider this Trunk-based since branches are created in some cases. I do consider it such because the only code that matters is on main
and in-progress work is merged into main
very frequently. Using working branches generally makes it easier for projects with multiple teams or pairs in the team working on the same code.
Certainly if there is no need to create a branch, then a branch should not be created. If you can pull main, add to the code (which includes testing it thouroughly), and then push it back to the remote, by all means do so. If you need to hand off the in-progress code for any reason (driver swap, have to go to meeting, have to take the dog for a walk, etc.) then creating a branch to push to for the hand off is the best way to handle that.
However, it is important to have the discipline to keep the life of the branch as short as possible. A day is generally as long as I care to hold on to a branch. You should resist with great vigor any call to use any of the Git Flow types of branch management schemes. Any system where there is a develop
branch and a separate production
branch or a branch for each release, should be viewed with disgust. These schemes are bound to bring more friction than to the delivery system.
Linear History
The main
branch should always have a Linear History. Working branches should be deleted as soon as they are merged into main
.
I really dislike seeing merge commits in main
. This is so ugly and can cause complications when doing any git history analysis.
I let git enforce this by setting the fast-forward-only configuration in the git config.
[merge]
ff = only
When this is set, git will not perform a merge that requires any possible conflict resolution.
There are rare cases where something has gone awry and requires an actual merge with resolutons. To override the config setting, add the --ff
command line option to the merge command.
git merge -ff that_problem_branch
I have never seen a case where this is really necessary, however. Any time where it this seems needed, you can create a branch to resolve the issues then fast-forward merge that branch to main
.
Rebasing
Working branches are rebased to main
frequently during the working phase and expecially before being merged back to main
so that the Linear History of main
is preserved. If there are no new commits on main
since the working branch was created, the rebase will be zero work. If there are some changes, then the conflict resolution will happen on the branch and should be simple because the branches are not long-lived. Once the branch has been rebased to main
it can be fast-forward merged to maintain the Linear History of main
.
There are those who say rebase is evil (or at least Mostly Bad) because it destroys history. I say rebase is a tool and, as with any tool, can be used for either good or evil. I use it for the good of keeping working branches up to date with main
while work continues and for the good of maintaining the Linear History of main
.
Squash Working branches
I also usually squash working branches that have had many commits because those commits are usually not helpful history. No one needs to see five commits with the comment "typo"
or 10 commits that are "created a failing test"
followed by the matching 10 which are "made the test pass"
. All of those commits on the working branch get squashed down to one commit with a clear comment on what feature was added to to the product.
I use a version of these steps to squash a branch that was made from main
git reset main
git add -A
git commit --edit -m "Some useful description"
There is actually more to it than that, but that is the gist. If main
has had any commits added since the branch you have to make sure to reset to either have rebased before the squash or to reset to the commit where the branch was made. I also do some work to gather all the commit messages from the working branch into the final comment message as well as any other commit authors when we are working in a group and passing the branch around during driver switches.
You could also use an interactive rebase or the --squash
option on a merge. I tend not to use those because I generally want to resolve the rebase to main
separately from the squash, usually will squash all the commits, and want to run tests after the squash but before merging to main
.
End Note
That’s the meat of it. There’s quite a lot you can do with a git
repository, but most of the time you don’t need much. Even the above short list is more than you will use on the normal days. For those you likely only need pull
, commit
, and push
.
I’m here if you ever want to talk about ways to use git
in your world.