Understanding remotes
#
So, before we go about fixing our out of date branch, let’s talk a little about
another fundamental git concept: remotes
A remote
in git is sort of like a pointer, but rather than point to a specific
file or commit. It points git itself to a place where a git repo is stored.
This is typically a remote server. Something serving git over https
or ssh
is fairly common.
For example, since this workshop comes from a repo hosted on GitHub it has two remotes that are available:
https://github.com/carsonoid/workshop-guts-of-git.git
git@github.com:carsonoid/workshop-guts-of-git.git
Both of these are valid remotes
for git.
A note about local remotes
#
This may seem like an oxymoron, but yes, you can use a local git repository as a remote!
This is important to know because we will be utilizing this feature heavily when working through various git branching exercises.
Back NextCreating the baseline repo #
While you can use the repo from Fundamentals, here is a script to help you fully recreate the ~/gitrepo
our commands expect.
By using the baseline you will also have a local repo that exactly matches the diagrams in the rest of this section.
WARNING: This will DELETE everything from
~/gitrepo
and~myclone
if either exists Make a backup if you want to keep work from that repo.
Show Script
You can simply click in the block below to copy the snippet and paste it into a terminal.
cd ~
bash <<EOF
set -e
rm -rf ~/gitrepo ~/myclone
mkdir -p ~/gitrepo
cd ~/gitrepo
git init
echo "# My Git Repository" > README.md
git add README.md
mkdir assets
curl -Lo assets/gopher.png \
https://go.dev/doc/gopher/doc.png
git add assets
git commit -m "Initial Add"
touch api
echo "## Has an API" >> README.md
git add .
git commit -m "feat: add api"
git tag v0.0.1
git checkout -b topic
echo
echo "======= Setup success! ======="
echo
echo "------- git log -------"
git log
EOF
Cloning from a local remote
#
To use a local repo as a remote, you can simply git clone
it.
git clone ~/gitrepo ~/myclone
cd ~/myclone
With that done, we can now examine and operate in ~/myclone
and do all the
same things that we would do if we used a full git server.
What ~/myclone
contains
#
From here on out you we will be visualizing the state of our git repo using stacks.
Each stack represents a head
of a git repo and it’s starting commit (at the top) and
all the commits that came before. It really isn’t much more than a git log
made using boxes.
Explained #
You can see that we are concerned with 3 heads right now:
Our local main
head.
#
The repo starting from the commit pointed to by the contents of refs/heads/main
The head at origin/main
#
The repo starting from the commit pointed to by the contents of refs/remotes/origin/main
NOTE: Remote Refs and .git
You will likely not actually have a file at .git/remotes/origin/main
This is because git stores most remote heads in a compacted file.
Try using ls-remote
instead
git ls-remote -q --heads
63241bfa5a195149e8b3dd3ec934ef4f97f2fa52 refs/heads/main
abd14ba38fd78839c2a6f24b50ee99f2f3934e7a refs/heads/topic
The head at stored in our remote #
The repo starting from the commit pointed to by the contents of refs/heads/main
as it currently exists in the remote.
Update the remote #
Let’s simulate someone updating main
on the remote.
cd ~/gitrepo
git checkout main
touch "users"
git add users
git commit -m "feat: add users"
cd ~/myclone
The snippet above emulates another user pushing new code to main
. It’s the
local repo equivalent of someone else pushing new code to a remote server like GitHub.
Meanwhile in ~/myclone
#
You will notice in our diagram that while we just added a new commit to the remote
absolutely nothing has changed in our local repo. Both main
and origin/main
are unaware of the new commit.
Fetch latest #
But this is easy to fix! We can use git fetch
to update our local repo based on the latest data
in the remote
git fetch
Now you can see that our origin/main
head now points to the the new commit.
Merge latest #
So, how do we ensure that our main
ref starts at the same place as origin/main
?
Easy! We use the same command we always use to combine to refs into one: git merge
git merge origin/main
Updating c5b4843..24f3e65
Fast-forward
users | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 users
Now you can see that our origin/main
head now points to the the new commit.
What about git pull
?
#
It may seem sort of odd to go to all this trouble. And even more odd to use git merge
to update our main
to match the latest main from our remote repo.
But the truth is that this is exactly what git pull
does.
You do not have to run the commands below, they will have no effect since our
main
is already up to date
git pull origin/main
Or, since our main
is already set up to track origin/main
we can skip the second
argument in our command. Git will assume we want to use the tracking head by default.
git pull
Next Section Next SectionYou could try this for yourself by following the exercise up to the
fetch
step and usinggit pull
instead.You will end up with the same git log regardless of method