- 1. Getting geeky with Git #1. Remotes and upstream branches
- 2. Getting geeky with Git #2. Building blocks of a commit
- 3. Getting geeky with Git #3. The branch is a reference
- 4. Getting geeky with Git #4. Fast-forward merge and merge strategies
- 5. Getting geeky with Git #5. Improving merge workflow with rebase
- 6. Getting geeky with Git #6. Interactive Rebase
- 7. Getting geeky with Git #7. Cherry Pick with Reflog
- 8. Getting geeky with Git #8. Improving our debugging flow with Bisect and Worktree
- 9. Getting geeky with Git #9. Understanding the revert feature
- 10. Getting geeky with Git #10. The overview of Git hooks with Husky
- 11. Getting geeky with Git #11. Keeping our Git history clean with fixup commits
Version control systems (VCS) are one of the essential tools of every programmer. The most popular one is Git, and therefore it is worth looking into it a bit more. In this article, we look into what is a remote and what the origin keyword means. We also check out what is an upstream branch and how we can benefit from defining it.
Git origin
You might have already used the origin keyword when performing various operations on your repository, for example, git push origin master.
In some of my examples below I use a repository from the TypeScript Express series
The best way would be to learn by example. Let’s start by pulling a repository:
1 |
git clone git@github.com:mwanago/express-typescript.git |
The above command clones a repository into a directory on our drive. Doing so defines a remote.
Git is a distributed version control system. Although we do most of the operations on a local copy of a repository, Git can also communicate with remotes.
Remotes are repositories other than our local versions. When we push and pull, we synchronize our local version of the repository with the remote.
After running git clone and going into our new directory, we can verify that we have a remote defined.
1 |
git remote |
origin
1 |
git remote get-url origin |
git@github.com:mwanago/express-typescript.git
So, the origin is an alias to a particular remote repository. Its name is a widely used convention that is set up for us by default.
We could provide a full path to our remote instead of using an alias.
1 |
git pull git@github.com:mwanago/express-typescript.git master |
Do we need to use the remote alias?
When running git push, we have a few options.
The first one is to be very explicit. Running git push origin master synchronizes specifically the master branch.
The second one is to be a little less explicit. We can run git push origin without the name of the branch. To complicate things a bit, the behavior of this command is configurable.
By default, git push origin pushes the current branch to its upstream branch.
What is upstream and how it connects to our local branches
The upstream branch is the branch tracked by our local branch. Putting the above simply, the upstream branch is the remote counterpart of a local branch.
On our repository, there is a branch called postgres. Let’s switch into it.
1 |
git checkout postgres |
Branch ‘postgres’ set up to track remote branch ‘postgres’ from ‘origin’.
Switched to a new branch ‘postgres’
1 |
git branch -vv |
master 687ad6e [origin/master] refactor(): use named imports from express
* postgres 4fcd357 [origin/postgres] test(Authentication): test if there is a token in the registration response
In the above output, we see origin/master and origin/postgres. Those two are remote-tracking branches. They act as local references to the state of the remote branches.
Our local branch postgres now tracks a remote branch in the origin remote.
Since our local branch tracks the remote branch, it is referred to as a tracking branch
Creating a brand new repository
To provide a real-world example, let’s create a new repository on GitHub.
The interesting part is git push -u origin master. Let’s break down what is happening above.
-u stands for –set-upstream
In a brand new repository, there are no branches at all. Creating our first commit and try to push our local master branch that was created in this process, it might not be enough.
1 |
git push origin master |
Doing only the above creates the master branch in our remote repository. Unfortunately, it doesn’t connect our local master with it.
1 |
git branch -vv |
* master d55e411 first commit
This might be troublesome! Let’s try to make some changes to README.md and push the changes.
1 |
git push origin |
fatal: The current branch master has no upstream branch.
To push the current branch and set the remote as upstream, use git push –set-upstream origin master
As we stated above, by default, git push origin pushes the current branch to its upstream branch. The issue is that we don’t have an upstream branch set up!
It would succeed if we were more explicit because we state where is the branch that we want to push to:
1 |
git push origin master |
The most straightforward approach to the above issue is to run git push -u origin master instead. It connects our local master through origin/master to the branch in our remote repository, making it an upstream branch.
As you can see, setting up an upstream branch gives us a possibility to be a bit less explicit. We could even run git push without the remote, and Git assumes that we want the remote of the current branch. Being as precise as possible when pushing changes might be a good thing, though.
Having upstream branches can be useful when doing other operations such as git pull.
How setting an upstream branch affects git pull
When we run git pull, we fetch the current state of the remote and merge it to our local repository.
When we run git pull, there are a few things Git needs to know.
- From where should it fetch
When running git pull origin, we indicate that we want to fetch from the origin. If we don’t specify it by running just git pull, the default is the remote associated with the branch we are currently on. To figure out the associated remote, git needs an upstream branch. - What should it fetch
When we run git pull origin master we explicitly say that we want to merge the remote branch master into our current branch. Not specifying the branch by running just git pull origin means that we want to merge the upstream branch into our current branch.
As you can see above, if we want to omit the arguments of git pull we need to set up an upstream branch. Doing so without one causes an error.
1 |
git pull |
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.git pull <remote> <branch>
If you wish to set tracking information for this branch you can do so with:
git branch –set-upstream-to=origin/<branch> maste
Summary
The terminology surrounding branches and remotes in Git is vast and can be quite confusing.
Remote is a repository other than our local copy. The origin keyword is an alias to the default remote connected to our local repository.
Since Git is distributed, we maintain local copies of branches. To connect to their remote counterparts, we locally have remote-tracking branches, for example, origin/master. They act as pointers to where the remote master is.
If our local branch tracks a remote branch through a remote-tracking branch, we call it a tracking branch. Its remote equivalent now acts as an upstream to our local branch.
While knowing all of the above might not be crucial to using Git in your everyday work, it gives you a broader perspective. It might also help when dealing with some issues.
Thank you!