Learning and configuring git push
About
OK, let's take the time to learn the default behaviours of git push instead of
fumbling around each time. ☺
I'm going to read the manual of the git for each things that I find a bit magical and will document them here.
Setup
After creating a repository on GitHub and following the initialization steps, we end up with .git/config file that looks like this:
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = https://github.com/augustfengd/foobar.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
remote = origin
merge = refs/heads/mainThe experience
Typically, one would branch off main, commit a few patches and then run git push:
# branch off
git switch -c feature
# commit some changes
echo foobar > helloworld.txt
git add helloworld.txt
# git push
git pushWith an default setup, such an operation will be met with this familiar error:
git push
# fatal: The current branch feature has no upstream branch.
# To push the current branch and set the remote as upstream, use
#
# git push --set-upstream origin feature
#
# To have this happen automatically for branches without a tracking
# upstream, see 'push.autoSetupRemote' in 'git help config'.git push
Let's investigate what git understand when we run git push.
According to the man page of git-push, the interpretation of that command verbatim will be git push [<repository> [<refspec>…]]
<repository>
Assuming the .git/config from earlier, the behaviour of omitting <repository> is to default to origin.
This behaviour can be changed by configuring the branch in .git/config:
[branch "feature"]
remote = xyz[<refspec>…]
Assuming the .git/config from earlier, the behaviour of omitting [<refspec>…] is to use the simple mode from the list of predefined behaviour in push.default.
The simple mode says that git push should push the current branch to a branch of the same name on remote.
Configuring the branch
We define the upstream branch for a given branch by introducing branch.<name>.remote and branch.<name>.merge to the branch's configuration in the .git/config file:
[branch "feature"]
remote = origin
merge = refs/heads/mainAn opinionated configuration
Note that the feature branch configuration from earlier is different than what
would happen when we run the command from advice: git push --set-upstream
origin feature.
The reason I target the master or main remote branch as upstream for my all branches instead of a remote branch with the same name is because:
- These are the branches that I want my changes to eventually land on.
- My branch's tracking status in relation to master is more informative than seeing how many commits I forgot to push.
In order to achieve this automagically, I need to change a few git settings.
The first one is to automatically setup the branch's upstream configuration upon branch creation.
branch.autoSetupMerge
This configuration controls this setup automation, and the inherit setting fits my need the most, since I want to keep the upstream for all my branches.
[branch]
autoSetupMerge = inheritpush.default
This configuration controls what happen when we don't specify [<repository> [<refspec>…]] after the git push command.
It's default value is simple, which is to push to upstream.
In my setup, upstream is always master so I use the current setting
instead which causes git push to push the current branch to one with the same
name on the remote.
[push]
default = current