/ GIT

Don't git push

I admit the title is a bit provocative. Of course, you need to push your changes. I should probably have renamed it "Don’t just git push", or "Don’t simply git push". But I’m sucker for clickbait titles.

My point is, you should never ever type:

git push

This begets the question, why? Answering this question is the subject of this post.

Back to basics

If you ever worked a bit with Git, you know that git push accepts the remote and the branch as parameters e.g.:

git push <remote> <branch>

In general:

  • <remote> is origin
  • <branch> is the branch you’re currently working on
git push origin master

When pushing on the same branch, the above can be replaced with:

git push <origin> HEAD

Optimizing keystrokes

Developers are a lazy bunch. I of course count myself in. After some time, we generally try to reduce the number of keys typed. In order to do that, we set the remote when pushing:

git push -u origin master

The result should be akin to:

Branch 'master' set up to track remote branch 'master' from 'origin'.

This is also visible in the project’s Git configuration file:

git/config
[branch "master"]
    remote = origin
    merge = refs/heads/master

It means that the local master branch tracks the remote origin/master branch. Now, just typing git push on the master branch will automatically push to origin/master.

Trouble on the rise

After a while, we’ll probably start tracking multiple branches. All is the best in the best of worlds. The usual workflow is the following: work on a specific branch, make a Pull Request, then merge to master. But one fateful day, we need to rework our local branch before pushing again.

git rebase -i <commit>
git push --force

At that point, we notice that all tracked branches are pushed at once! With --force!!!

We go back to square one, vowing never to push without parameters again. And yet, the solution is within our reach.

To prevent any kind of trouble, one should never use --force but --force-with-lease option. Just saying.

Push defaults

Let’s have a look at the documentation:

push all branches having the same name on both ends. This makes the repository you are pushing to remember the set of branches that will be pushed out (e.g. if you always push maint and master there and no other branches, the repository you push to will have these two branches, and your local maint and master will be pushed there).

To use this mode effectively, you have to make sure all the branches you would push out are ready to be pushed out before running git push, as the whole point of this mode is to allow you to push all of the branches in one go.

— Git documentation
https://git-scm.com/docs/git-config#git-config-pushdefault

Fortunately, several options are available to replace this default.

Push options

There are several options available:

Option Description Notes

nothing

Does not push anything if no branch is set

Default in Git 1.x

matching

Pushes all branches having the same local and remote name

tracking/upstream

Pushes the current branch to its upstream branch

simple

Like upstream, but refuses to push if the upstream branch’s name is different from the local one

current

Pushes the current branch to a branch of the same name

Default in Git 2.x

Version defaults seems to depend on the version that was initially installed, not on the runtime version. If you started using Git before 2.x - like me, chances are the default is still matching.

To set the default behavior, use the following:

git config --global push.default simple

Of course, the default can then be overriden on a specific Git project:

git config push.default nothing

Conclusion

Typing git push without any argument might cause issues if one is not aware of the push.default configuration options. Tweaking this oh so tiny parameter can make a huge difference between being more productive and damaging the repository, along with one’s relationships with the team.

Nicolas Fränkel

Nicolas Fränkel

Developer Advocate with 15+ years experience consulting for many different customers, in a wide range of contexts (such as telecoms, banking, insurances, large retail and public sector). Usually working on Java/Java EE and Spring technologies, but with focused interests like Rich Internet Applications, Testing, CI/CD and DevOps. Also double as a trainer and triples as a book author.

Read More
Don't git push
Share this