Assuming your work version of Git is pre-2.0 (your comment suggests it may be 1.8), that would be the reason your home Git (which 2.0 or later) and work Git (pre-2.0) behave differently.
In Git 2.0, the default value for push.default
changed from matching
to simple
. Starting with Git 1.8.0, Git began producing warning messages about this. See Warning: push.default is unset; its implicit value is changing in Git 2.0 for details. Git version 2.8.0 dropped the warning.
Note that you may prefer current
to simple
. See "simple" vs "current" push.default in git for decentralized workflow. However, setting an upstream is useful: see Why do I need to do `--set-upstream` all the time? Read on for more background if you like.
Configuration
Whether as a result of this, or just because you decided you should configure it, you may have set your own value for push.default
, either in any particular repository, or for your own personal all-repositories-wide --global
setting. (Note that if you git config --global
some setting, and then also git config
the same setting locally in one specific repository, the local setting usually overrides. There are a few exceptions to this rule, e.g., for branch.master.fetch
, but it tends to be unwise to set this to anything with --global
!)
Matching, simple, and other modes
If you have not set it, or have set it explicitly to matching
in your work setup but to simple
in your home setup. the different actions of these two modes explain the issue. The behavior of matching
is somewhat described in the accepted answer to Warning: push.default is unset; its implicit value is changing in Git 2.0, and much more in Default behavior of "git push" without a branch specified—but note that both of these describe what you get if you run:
git push sensorAtHome
or:
git push
but not:
git push sensorAtHome pull-down-to-refresh
More precisely, descriptions always start out talking about what happens when you push with no refspecs. (We'll get to refspecs in just a moment.)
There are actually five possible settings for push.default
(although the new standard simple
was only introduced in Git version 1.7.11, and there are still some people using Git 1.7). These five settings are nothing
, current
, upstream
, simple
, and matching
.
The nothing
setting is actually the simplest of all, but I tried it and found it annoying. :-) It forces you to name which branch you want to push. Because of this, we can mostly ignore it and only think about the other four.
The other four settings will intuit some branch or branches to push if you don't specify any branches. More precisely, these four settings intuit things if you leave out all the refspecs. But they can also affect what happens when you include some refspecs.
The git push
syntax
The syntax for git push
, if we ignore all the flags arguments, is:
git push <repository> <refspec> <refspec> ...
That is, the first argument after git push
(also skipping any flags and flag arguments) is the repository. You can write out a full URL here, e.g.:
git push https://github.com/...
but it's usually much nicer to use a remote, which is a short name like origin
, or in your case, sensorAtHome
. For git push
, the remote mostly just avoids having to type a long URL each time (for git fetch
it also provides the origin/
part of the remote-tracking branch names).
After the repository argument, any remaining arguments are refspecs. The repository argument is actually optional, but if you want to give any refspec arguments at all, you must provide a repository argument first. But what exactly is a refspec? Why would we care about them?
Refspecs
The simplest form of a refspec is the one you are using here: it's just a branch name. You write:
git push someremote branch
and Git pushes the named branch. But refspecs are actually much more general.
First, a refspec starts off with two parts separated by a colon. For instance, instead of just saying branch
, you can write:
git push someremote branch:branch
The name on the left is your name, and the name on the right is their name. Remember that when you run git push
, you are using two Gits, with two different repositories. You are telling your Git to call up some remote Git. Once your Git has the other Git on the Internet-phone (via https or ssh or whatever), your Git sends some of your commits to their Git, and then your Git asks them to set their branches, usually based on the commits you just sent.
Since there are two Gits, there are two different branch names involved. Your branch might be named Fred, and theirs might be named Frederick-the-Great, for instance. Yours might be Zaphod and theirs might be Beeblebrox. Your branch is yours, and their branch is probably your upstream. There's no requirement that they have the same name—well, almost no requirement. And, if you literally spell out both parts, writing zaphod:beeblebrox
or whatever, Git assumes you know what you are doing, and runs with that.
Things get pretty crazy if these names are not the same, though. It's much simpler if they match all the time. So, three of the four "interesting" settings—matching
, current
, and simple
—try to make sure they stay the same. You just need to use your names, and your Git will try to ensure that their names match up.
The one setting that does not do this—the upstream
mode—tells your Git to use your name on your side, and whatever you have configured as the upstream setting on their side. Obviously, for this to work, you must set an upstream. But this still leaves matching
, current
, and simple
, and may leave you wondering what they are for.
The short answer is that matching
is what Git did originally, but it turned out to be a mistake and you probably should never use it. You should use either simple
or current
instead. The simple
setting is safer, but requires that you set an upstream. Again, for a bit more and to help you choose between them, see "simple" vs "current" push.default in git for decentralized workflow.
If you provide at least one refspec, the old matching
setting works just like current
. Your Git takes the refspec or refspecs (i.e., branch name) you provided—and remember, this is only for when you didn't write local-name:remote-name
, so there's just a local name—and has their Git create or update a branch with the same name, whether or not your branch has an upstream set. But if you leave out all the refspecs, matching
tells your Git to ask their Git about all their branches, and look up all your branches, and match up the names. Wherever the names are the same, your Git sends your commits to their Git, and asks them to set their same-named branch.
For most people, at most times, this difference is small. You have your master
, and maybe your develop
and a feature branch or two. You git fetch
to pick up new stuff, work for a while, and git push
to send what you wrote. Your Git asks their Git to update master
and develop
and your feature branches. If you were not supposed to be working on master
, and you didn't work on master
—just on develop
—there's nothing in your master
for your Git to push, so there is no problem. Even if someone else pushed something new to the other Git's master, you just get part of your push rejected with an error: your develop
changes get pushed and your attempt to remove their new commits from their master
meets with an error.
But look: you just asked your Git to delete their new commits from their master
. That's a bad sign, if nothing else. And, if you did some experimental work on a feature branch, and it's not actually ready to push yet and you plan to fix some stuff and rebase some bad commits away in that feature branch, you may have just accidentally pushed both develop
and that feature branch.
It's just bad all around. The current
setting is a whole lot like the matching
setting, but it pushes only one branch by default, which is the one you have checked out now.
The simple
setting is just like the current
setting, but adds one more safety belt: the current branch needs to have its upstream set, to a branch of the same name in the other Git.
Refspecs are more general than just branches
For completeness, I want to mention a few more things about refspecs. One is that they don't have to name branche: you can also name tags. Your Git will generally figure out which one you mean, provided you don't use the same name for both a tag and a branch (don't do this—Git has a defined set of rules for what happens, but they are weird and conflict-y and will confuse you). You can spell out the "full name" of any reference: refs/heads/master
, refs/tags/v1.2
, and so on. You can leave out the local name, by writing :delete
, which asks their Git to delete a branch or tag or other reference. Last, you can set a per-refspec force flag.
Summary
These are the five possible settings for push.default
:
nothing
: you must include at least one refspec argument (which forces you to include the remote part as well). You can't really go wrong with this setting; the problem is that it's quite annoying, i.e., you can't just go right either.
matching
: this is the old, pre-2.0 Git behavior. It can push too many branches, so don't use it unless you're really stubborn. :-)
current
: this is the better-behaved variant of matching
.
simple
: this is the same as current
with the added safety-check that your branch needs to have an upstream set, with the same basic branch name. The safety-check can be slightly annoying: it forces you to set the upstream. Setting the upstream has value other than just making simple
happy, though, so this is really the best push.default
for most people most of the time.
upstream
: this is for the slightly-crazy-making case where, for some reason, you have to name your branch fred
even though the upstream is ginger
, or whatever. It's kind of a more permissive variant of simple
: you still have to set the upstream, but you can set it to take a trip on the crazy train.