The git push
command actually takes this as an argument. Let's start with a more detailed command:
git push origin event-api:abc
This tells your Git that it should:
- Call up some other Git at a URL you have stored using the name
origin
;
- Offer it the last commit on your
event-api
branch, by that commit's hash ID;
- Send any commits that the other Git asks for, based on the offer in step 2; and last
- Ask the other Git to set its branch named
abc
to the commit offered in step 2.
That is, when you run git push
, it's your Git that decides what to ask of the other Git.
Now, if you leave out the colon:
git push origin event-api
you might sensibly ask: which branch is my Git going to ask their Git to set?
The answer is complicated. However:
This command pushed event-api
→ develop
I have trouble believing this—to believe it, I'd have to see the exact output from your git push
command.
Here is what the git push
documentation has to say about this kind of git push
. Note that the event-api
string, despite the lack of a colon and a second name, is a refspec in Git terms, and the paragraph quoted here talks about how refspecs are treated:
The <dst> tells which ref on the remote side is updated with this
push. Arbitrary expressions cannot be used here, an actual ref must
be named. If git push [<repository>]
without any <refspec>
argument
is set to update some ref at the destination with <src>
with
remote.<repository>.push
configuration variable, :<dst>
part can be
omitted—such a push will update a ref that <src>
normally updates
without any <refspec>
on the command line. Otherwise, missing
:<dst>
means to update the same ref as the <src>
.
So, before we can say what :<dst>
your Git will fill in, we must ask whether you have a configured remote.origin.push
setting. If you do, that determines which :<dst>
is implied.
Most people don't have any such settings. You have to be something of a Git guru just to find the information in the git config
documentation, or to understand the paragraph quoted above, to know that there is such a variable.
If you don't have this set, which is what I suspect, then git push origin event-api
is simply shorthand for git push origin event-api:event-api
. That is, your Git asks their Git to set (or create) their event-api
branch.
If you run:
git push
without writing out origin
and event-api
, or:
git push origin
without writing out event-api
, another set of rules take over. Here, the most important questions—or at least the first two to ask—are: What Git version are you running? and Have you set push.default
?
The push.default
setting in Git version 2.0 or later is simple
. With simple
, your initial push must generally use git push -u
; after that, git push
behaves sensibly, pushing your event-api
to their event-api
. The reasons for this are a bit complicated, and you can choose other settings. But in Git versions predating 2.0, which are still the standard versions installed by some Linux distributions, the default push.default
setting is matching
.
With the matching
setting, a git push
that omits the name(s) of what branch or branches to push works by having your Git ask the other Git which branches they have. Let's say they have exactly two branch names, master
and develop
, while you have three branch names, master
, develop
, and event-api
. So their Git will list out master
and develop
. Your Git then goes through your three names and matches each against the two names they sent. The result is the two names they sent.
(If you had deleted your master
and/or develop
—which is something you can do; there's no requirement that your Git have any branch names in particular—then you'd have one or zero matching names in this step. But presumably you have these three names, and they probably have just those two.)
Your Git will now, in step 2, offer the last commit on your master
branch, and offer the last commit on your develop
branch. These are the two matching names, so these are the two commits your Git will offer. Their Git will probably already have those commits, but if they don't, they will, in step 3, ask for those commits, and any other commits required to support those commits.
In any case, having gotten through steps 2 and 3, your Git will now ask the other Git to set its master
and its develop
to the two hash IDs from your own Git's master
and develop
respectively. If this makes no changes, you see nothing at all here, but if you did have new commits for them, your Git will send those commits in step 3, and you will see one or both names get updated in step 4.
What to remember here
Remember these things about git push
:
Your Git calls up another Git. To do this, it needs a URL. You will generally use a name like origin
here; origin
is a remote and a remote stores a URL.
Your git push
then pushes commits. Specifically, your Git needs commit hash IDs. Your Git gets these hash IDs from your branch names, which need not match the other Git's branch names. We humans tend to use matching branch names for our own sanity: Git doesn't really care, but we do.
Having sent some commit or commits if needed, your git push
ends by sending the other Git one of the following:
- A polite request: Please, if it's OK, set your branch name ______ to commit hash ID ______.
- A command: Set your branch name ______ to commit hash ID ______!
- A conditional command: I think your branch name holds hash ID ______. If so, set it to hold ______ instead.
In all three cases, they tell your Git whether they did it, and if not, why not (which your Git prints as a "rejected" error).
The arguments in git push remote refspec...
are the remote, which supplies the URL, and the refspecs (one or more of them), which supply both the local commit hash ID—based on a name, usually, but you can use a raw hash ID if you want—and the name they should set on their end.
(If you do use a raw hash ID, you may have to send a fully-qualified name, like refs/heads/event-api
, as there's now no easy way for your own Git to guess whether you mean the name as a branch name, a tag name, or some other kind of name.)
If you omit the colon in a refspec, the branch name your Git will ask their Git about is normally the same name you used. However, several configuration settings, such as setting push.default
to upstream
, can change this. If you do use the upstream
setting, the control here is what you have set for the branch's upstream. See Why do I have to "git push --set-upstream origin <branch>"?