Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

1.2 Introduction to Git

Now that you have a handle on the basic command-line tools, you’re ready to start with Git. Git is a version control system that runs on the command line, which is why we started there.

First, let’s check if Git is installed and what version you have.

git --version
git version 2.53.0

If this command returns a version number (e.g., git version 2.34.1), you’re ready to go. If you get an error, you’ll need to install Git first.

Configuring Git

The first thing you should do after installing Git is to tell it who you are. This information is attached to every change you make, so it’s important for collaboration.

To set your username and email address for all your projects (globally), use the git config command:

git config --global user.name "mcallara"
git config --global user.email "msdp.book@gmail.com"

To check your settings, you can list the global configuration:

git config --global --list
user.name=mcallara
user.email=msdp.book@gmail.com

1.3 Local repositories and commits

In this chapter, we will explore the creation of local repositories and the process of committing changes. We will also learn how to interact with Git using the command line and Visual Studio Code (VSC).

Creating a dummy project

If we want to learn about Git, we need a project to work with. Git can track changes in any type of files, it doesn’t have to be code. So to keep it simple, we will create a dummy project, which will be just a directory with some text files in it.

Source
mkdir my-project
cd my-project
ls -a

Initialize a repository

To tell Git that you want it to keep track of your project changes, we need to initialize a Git repository. To do that we use the git init command.

git init -b main
Initialized empty Git repository in /home/runner/work/msdp-book/home/ch1/my-project/.git/
ls -a
.  ..  .git

Check the repository status:

git status
On branch main

No commits yet

nothing to commit (create/copy files and use "git add" to track)

Deleting the Git repository

To delete the repository, we can just simply delete the .git folder, we can do this with the rm command followed by the -rf option (to delete all the content without confirmation) and the path to the .git folder:

rm -rf .git

After deleting the repository, all the changes made to the files in the working directory will remain, but the history of the changes will be lost.

If you try this command, you will need to initialize the repository again with:

git init -b main
Initialized empty Git repository in /home/runner/work/msdp-book/home/ch1/my-project/.git/

The three basic sections of Git

So we have a directory for our project and a repository (the .git directory) associated with it but how do we actually keep track of the changes in our project? To keep track of the changes, Git uses three areas: the working directory, the staging area, and the repository to allow the user to generate snapshots of the project (that we call commits).

  1. The working directory is the area in which you create, edit and delete files.

  2. The staging area, or index, is a file, stored in the .git directory, that stores information about what will go into your next commit.

  3. The repository is where git stores all the commits, the snapshots of the content of your working directory that was staged for a commit. Git generates a commit history by linking each commit to previous commits.

Committing changes

Source
touch file1.txt
echo "This is the first line." >> file1.txt

Now we have a file in the working directory. Let’s check the repository status using the git status command.

git status
On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	file1.txt

nothing added to commit but untracked files present (use "git add" to track)

The two steps for a commit: add and commit

To ‘move’ a file from the working directory to the staging area, we use the git add command.

git add file1.txt
git status
On branch main

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
	new file:   file1.txt

To ‘move’ all the changes in the staging area to the repository, we use the git commit command. We also need to add a commit message to describe the changes we made using the -m option.

git commit -m "Create file1.txt with the first line"
[main (root-commit) 90fcf43] Create file1.txt with the first line
 1 file changed, 1 insertion(+)
 create mode 100644 file1.txt
git status
On branch main
nothing to commit, working tree clean

Listing the commits

We can list the commit history using the git log command.

git log
commit 90fcf4335b70e4e5df2ed0b34a2adab1161a0360 (HEAD -> main)
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:12 2026 +0000

    Create file1.txt with the first line

A commit behind the scenes

When we commit changes, Git creates a new object in the .git/objects directory. This object contains the changes we made to the files, the author, the date, and the commit message.

ls -a .git/objects
.  ..  59  90  c0  info  pack

1.4 Branches

In this section, we will learn about branches in Git. We will discuss why they are useful, what they are, how to create them, and how to switch between them.

Motivation for branches

Branches allow you to diverge from the main line of development and work independently without affecting the main line. This is useful when you want to work on a new feature or fix a bug without affecting the main line of development. Once you are done with your work, you can combine your changes back into the main line.

What are branches?

A branch is a lightweight movable pointer to a commit. When Git initializes a repository, it creates a branch. As you commit changes, Git moves the branch pointer forward to point to the latest commit. In our repository, we used the option b with the argument main to indicate that the initial branch should be named main.

Source
git log
Output
commit 90fcf4335b70e4e5df2ed0b34a2adab1161a0360 (HEAD -> main)
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:12 2026 +0000

    Create file1.txt with the first line

Modified files in Git

Let’s add some commits to our commit history to see how the branch pointer moves. Let’s add a new line to our file1.txt file and check the status of the repository.

echo "This is the second line." >> file1.txt
git status
On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   file1.txt

no changes added to commit (use "git add" and/or "git commit -a")

Staging files with VSC

This time, instead of using the command line, we will use VSC to stage the changes.

  1. Open the Source Control Panel: In VSC, click on the Source Control icon on the sidebar or press Ctrl+Shift+G (Cmd+Shift+G on macOS) to open the Source Control panel.

  2. View Changes: You’ll see a list of changed files in the Source Control panel. These files are modifications in your working directory that Git has not yet committed.

  3. Stage Files:

    • To stage an individual file, hover over the file name and click the + icon. This action stages that specific file.

    • To stage all changes, click the + icon next to the “Changes” section at the top of the list. This stages all modified files.

Committing with VSC

Now that we have staged changes, we can commit them.

  1. Enter a Commit Message: At the top of the Source Control panel, you’ll find a text field to enter your commit message. Enter “Add second line to file1.txt” as the commit message.

  2. Commit the Changes:

    • To commit the staged changes, click the checkmark icon () above the text field where you entered your commit message. Alternatively, you can press Ctrl+Enter (Cmd+Enter on macOS) to commit.

Checking how the branch pointer moves

Let’s check the commit history again to see how the branch pointer moves.

git log
commit 06b6a5b53032d9eee4f2363ca6c6cfe818b04500 (HEAD -> main)
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:13 2026 +0000

    Add second line to file1.txt

commit 90fcf4335b70e4e5df2ed0b34a2adab1161a0360
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:12 2026 +0000

    Create file1.txt with the first line

Listing local branches

So far we have been working with the main branch. Let’s list the branches in our repository. To list the branches, we use the git branch command.

git branch
* main

Creating a new branch

Let’s imagine that we want to add a new feature to our project. We will create a new branch called feature. To create a new branch, we use the git branch command followed by the name of the new branch.

git branch feature
Source
git branch
Output
  feature
* main

Since our current branch is main, if we commit changes, they will be added to the main branch and not to the feature branch.

Source
git log
Output
commit 06b6a5b53032d9eee4f2363ca6c6cfe818b04500 (HEAD -> main, feature)
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:13 2026 +0000

    Add second line to file1.txt

commit 90fcf4335b70e4e5df2ed0b34a2adab1161a0360
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:12 2026 +0000

    Create file1.txt with the first line

How does Git store branches?

Git stores branches as files within the .git/refs/heads/ directory. Let’s list the files in this directory.

ls .git/refs/heads
feature  main

A file is created for each branch. Let’s look at the contents of the feature file.

cat .git/refs/heads/feature
06b6a5b53032d9eee4f2363ca6c6cfe818b04500

The file contains the hash of the commit to which the branch is pointing.

cat .git/HEAD
ref: refs/heads/main

The HEAD file contains the reference to the current branch.

Switching to the new branch

git switch feature
Switched to branch 'feature'
git branch
* feature
  main
git log
commit 06b6a5b53032d9eee4f2363ca6c6cfe818b04500 (HEAD -> feature, main)
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:13 2026 +0000

    Add second line to file1.txt

commit 90fcf4335b70e4e5df2ed0b34a2adab1161a0360
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:12 2026 +0000

    Create file1.txt with the first line

Let’s now create our next commit, add a new line to the file1.txt file with the message This is the third line. and commit the changes.

echo "This is the third line." >> file1.txt

git add file1.txt
git commit -m "Add third line to file1.txt"
[feature cf5639f] Add third line to file1.txt
 1 file changed, 1 insertion(+)
git log
commit cf5639f09964baaf487c66420f818bf086074750 (HEAD -> feature)
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:14 2026 +0000

    Add third line to file1.txt

commit 06b6a5b53032d9eee4f2363ca6c6cfe818b04500 (main)
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:13 2026 +0000

    Add second line to file1.txt

commit 90fcf4335b70e4e5df2ed0b34a2adab1161a0360
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:12 2026 +0000

    Create file1.txt with the first line

The Commit history diagram

As the number of commits grows, it becomes harder to keep track of the commit history. This is where representing the commit history with a diagram comes in handy. In our diagram, we will represent commits as circles, branches with boxes and the HEAD pointer with a diamond.

1.5 Merging Branches

In this section, we’ll see how to integrate work from the feature branch back into the main branch.

Types of Merges

The two most common merge strategies are fast-forward and three-way merges:

Fast-forward merge

Let’s first understand visually how a fast-forward merge of the feature branch into main would look by comparing the current state of the repository with the state after the merge.

This is how the repository looks now:

How can we incorporate the changes from feature into main? If we look at the commit history, we can see that main is behind feature by one commit. To update main with the changes from feature, we can simply move the main pointer to the same commit as feature. This is possible whenever you can update a branch to match another by advancing its pointer through the commit history until it reaches the same commit. This process is known as a ‘fast-forward’ because it involves moving the pointer forward to the commit of the other branch without creating a new merge commit.

So after the fast-forward merge, the repository would look like this:

Now that we understand what a fast-forward merge is, let’s see how to do it in Git. To perform a fast-forward merge, first switch to the branch you want to merge into, and then merge the other branch into it using git merge <branch-name>. For example, to merge feature into main:

git switch main
Switched to branch 'main'
git merge feature
Updating 06b6a5b..cf5639f
Fast-forward
 file1.txt | 1 +
 1 file changed, 1 insertion(+)
git status
On branch main
nothing to commit, working tree clean

After the fast-forward merge, there are no changes to commit; the working tree is clean.

git log
commit cf5639f09964baaf487c66420f818bf086074750 (HEAD -> main, feature)
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:14 2026 +0000

    Add third line to file1.txt

commit 06b6a5b53032d9eee4f2363ca6c6cfe818b04500
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:13 2026 +0000

    Add second line to file1.txt

commit 90fcf4335b70e4e5df2ed0b34a2adab1161a0360
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:12 2026 +0000

    Create file1.txt with the first line

We see that all the changes that we discussed in the diagram have been made. The main branch now points to the same commit as feature, and the feature branch still points to the same commit. The HEAD pointer is now pointing to main.

Impact of switching branches on the working directory

We will now explore what happens to the working directory when we switch branches. To see this, let’s first add a new file and make changes to an existing file on the feature branch, and then switch to the main branch.

git switch feature
touch file2.txt
echo "This is the first line." >> file2.txt
echo "This is the fourth line." >> file1.txt
git add .
git commit -m "Add file2.txt and modify file1.txt"
Switched to branch 'feature'
[feature 8bc379b] Add file2.txt and modify file1.txt
 2 files changed, 2 insertions(+)
 create mode 100644 file2.txt
ls
cat file1.txt
file1.txt  file2.txt
This is the first line.
This is the second line.
This is the third line.
This is the fourth line.
git switch main
Switched to branch 'main'
ls
cat file1.txt
file1.txt
This is the first line.
This is the second line.
This is the third line.

Git updates the files in your working directory to reflect the state of the files in the new branch. This means that any files unique to the previous branch but not present in the new one may be removed, and any files unique to the new branch may be added or modified.

Switching branches with uncommitted changes

Git prevents loss of work by disallowing branch switching with uncommitted changes. To see this in action, let’s make changes to file1.txt on the feature branch and then try to switch to main without committing the changes.

git switch feature
echo "This is the fifth line." >> file1.txt
Switched to branch 'feature'
git switch main
error: Your local changes to the following files would be overwritten by checkout:
	file1.txt
Please commit your changes or stash them before you switch branches.
Aborting
Fetching long content....

Modifying a staged file

Changes made after staging are not automatically included in the staged snapshot. To include changes in the staged snapshot, the file must be staged again.

git add file1.txt
echo "This is the sixth line." >> file1.txt
git status
On branch feature
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	modified:   file1.txt

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   file1.txt

We can also see the status in a more compact form using the -s option:

git status -s
MM file1.txt

The first character in the output of git status -s shows the status of the staged snapshot, and the second character shows the status of the working directory.

Let’s now stage the latest changes to file1.txt

git add file1.txt
git status -s
M  file1.txt

now all modifications have been staged and we can commit them:

git commit -m "Add fifth and sixth lines to file1.txt"
[feature 1959c7c] Add fifth and sixth lines to file1.txt
 1 file changed, 2 insertions(+)

Viewing all commits

When working with multiple branches in Git, you might find yourself on a branch that is behind others in terms of commits. For instance, if you’re on the main branch that hasn’t been updated with the latest commits from a feature branch, using the git log command while on main will only show the commit history up to the point main is currently at. This means you won’t see the commits that are on feature or any other branch until they are merged into main.

This is because git log displays by default only the commit history of that branch, starting from the current commit and tracing back through the history of commits that lead to the current state of the branch.

Let’s see this in action by using the git log command while on the main branch.

git switch main
git log
Switched to branch 'main'
commit cf5639f09964baaf487c66420f818bf086074750 (HEAD -> main)
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:14 2026 +0000

    Add third line to file1.txt

commit 06b6a5b53032d9eee4f2363ca6c6cfe818b04500
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:13 2026 +0000

    Add second line to file1.txt

commit 90fcf4335b70e4e5df2ed0b34a2adab1161a0360
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:12 2026 +0000

    Create file1.txt with the first line

Now compare this with the output of git log --all:

git switch main
git log --all
Already on 'main'
commit 1959c7ce9c54a5004102c74bf92bf8c3a4b4950d (feature)
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:17 2026 +0000

    Add fifth and sixth lines to file1.txt

commit 8bc379b95ae9a96b7023b5a1ea58767aa2722211
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:15 2026 +0000

    Add file2.txt and modify file1.txt

commit cf5639f09964baaf487c66420f818bf086074750 (HEAD -> main)
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:14 2026 +0000

    Add third line to file1.txt

commit 06b6a5b53032d9eee4f2363ca6c6cfe818b04500
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:13 2026 +0000

    Add second line to file1.txt

commit 90fcf4335b70e4e5df2ed0b34a2adab1161a0360
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:12 2026 +0000

    Create file1.txt with the first line

Checking out a commit and the detached HEAD State

We have seen that we can move the HEAD pointer to a specific branch by using git switch <branch-name> but we can also move the HEAD pointer to a specific commit by using git checkout <commit-hash>. We can also checkout a commit relative to the current position of the branch pointer by using git checkout <branch>~<number>. This is useful for exploring the history of a repository.

git checkout feature~2
Note: switching to 'feature~2'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at cf5639f Add third line to file1.txt
git status
HEAD detached at cf5639f
nothing to commit, working tree clean
git log --all
commit 1959c7ce9c54a5004102c74bf92bf8c3a4b4950d (feature)
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:17 2026 +0000

    Add fifth and sixth lines to file1.txt

commit 8bc379b95ae9a96b7023b5a1ea58767aa2722211
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:15 2026 +0000

    Add file2.txt and modify file1.txt

commit cf5639f09964baaf487c66420f818bf086074750 (HEAD, main)
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:14 2026 +0000

    Add third line to file1.txt

commit 06b6a5b53032d9eee4f2363ca6c6cfe818b04500
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:13 2026 +0000

    Add second line to file1.txt

commit 90fcf4335b70e4e5df2ed0b34a2adab1161a0360
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:12 2026 +0000

    Create file1.txt with the first line

When you check out a commit, you are in a detached HEAD state. This means that the HEAD pointer is no longer pointing to a branch, but to a specific commit. This is useful for inspecting the state of the repository at a specific point in time, but it is not recommended to make changes in this state. If you make changes and commit them, they will be based on the commit you checked out, not on the tip of any branch. This means that if you switch back to a branch, the changes you made in the detached HEAD state will not be part of the branch. To exit a detached HEAD state and retain your changes, you can create a new branch from the current commit:

git switch -c new-branch-name
Switched to a new branch 'new-branch-name'

This command creates and switches to the new branch (in one command) starting from the current commit, effectively bringing your HEAD back to a non-detached state and ensuring that any commits made in the detached HEAD state are not lost.

git status
On branch new-branch-name
nothing to commit, working tree clean

After creating and switching to the new branch we are no longer in a detached HEAD state, and the changes we made are now part of the new branch.

Deleting a branch

Finally, once your feature is merged, you usually don’t want to keep the feature branch around. To delete a branch, first you need to ensure that you are not currently on the branch you want to delete by switching to another branch or commit. Then use the git branch -d <branch-name> command. For example, to delete the new-branch-name branch:

git switch main
git branch -d new-branch-name
Switched to branch 'main'
Deleted branch new-branch-name (was cf5639f).

The -d option deletes the branch safely, meaning it will prevent you from deleting a branch that contains unmerged changes. If you are sure you want to delete the branch even if it contains unmerged changes, you can use the -D option, which forces the deletion.

1.6 Remote Repositories

In this section you will see how to create and manage your first remote repository with Github, including remote configuration, pushing changes, and cloning repositories.

Creating and commiting to a remote repository on Github

Create the remote repository

We will start by creating a remote repository on Github using a Web browser. We need to log into our Github account.

In the upper-right corner of any page, select +, then click New repository.

Use my-project as the repository name, and select Public. You can also add a description if you want. Do not initialize the repository with a README, .gitignore, or license, as we will do that later.

Click Create repository.

Setting up your local project to push changes to a remote repository on Github

Inside the my-project directory, we will tell Git that we want to work with a remote repository on Github.

Adding a remote repository to your local repository

To add a remote repository, use the remote add <short name> <url> command. This command adds, to your local repository, a reference to a remote repository. We will follow the convention of using origin as the short name of the remote repository. For the URL we will use the SSH URL of the remote repository on Github.

For Github user mcallara, and a repository named my-project the command to add the remote repository would be:

git remote add origin https://github.com/mcallara/my-project.git

List the remote repository connections

Git provides the remote command to list the remote repositories linked to your local repository.

git remote
origin

With the -v option, you can see the URLs used for fetching and pushing data.

git remote -v
origin	https://github.com/mcallara/my-project.git (fetch)
origin	https://github.com/mcallara/my-project.git (push)

Inner workings: remote config

If we inspect the .git/config file, we can now see the configuration for the remote repository.

cat .git/config
[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
[remote "origin"]
	url = https://github.com/mcallara/my-project.git
	fetch = +refs/heads/*:refs/remotes/origin/*

Checking references

Even though we configured the remote repository, we have not yet pushed any changes to it. Therefore, the .git/refs directory does not contain any references to the remote repository. If we look into the .git/refs directory to see references, we still only see heads and tags.

ls .git/refs
heads  tags

Pushing to the remote repository

Push your changes to the remote repository on Github, setting origin as the upstream for main.

git push -u origin main
Enumerating objects: 9, done.
Counting objects:  11% (1/9)
Counting objects:  22% (2/9)
Counting objects:  33% (3/9)
Counting objects:  44% (4/9)
Counting objects:  55% (5/9)
Counting objects:  66% (6/9)
Counting objects:  77% (7/9)
Counting objects:  88% (8/9)
Counting objects: 100% (9/9)
Counting objects: 100% (9/9), done.
Delta compression using up to 4 threads
Compressing objects:  25% (1/4)
Compressing objects:  50% (2/4)
Compressing objects:  75% (3/4)
Compressing objects: 100% (4/4)
Compressing objects: 100% (4/4), done.
Writing objects:  11% (1/9)
Writing objects:  22% (2/9)
Writing objects:  33% (3/9)
Writing objects:  44% (4/9)
Writing objects:  55% (5/9)
Writing objects:  66% (6/9)
Writing objects:  77% (7/9)
Writing objects:  88% (8/9)
Writing objects: 100% (9/9)
Writing objects: 100% (9/9), 761 bytes | 761.00 KiB/s, done.
Total 9 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/mcallara/my-project.git
 * [new branch]      main -> main
branch 'main' set up to track 'origin/main'.

Now that we have pushed main to the remote repository, we can see it on Github. Navigate to the my-project repository to see the commit history. Note that only main was pushed; the feature branch still exists only locally.

To push the feature branch to the remote repository, we can use the same command but replace main with feature:

git push -u origin feature
Enumerating objects: 9, done.
Counting objects:  11% (1/9)
Counting objects:  22% (2/9)
Counting objects:  33% (3/9)
Counting objects:  44% (4/9)
Counting objects:  55% (5/9)
Counting objects:  66% (6/9)
Counting objects:  77% (7/9)
Counting objects:  88% (8/9)
Counting objects: 100% (9/9)
Counting objects: 100% (9/9), done.
Delta compression using up to 4 threads
Compressing objects:  16% (1/6)
Compressing objects:  33% (2/6)
Compressing objects:  50% (3/6)
Compressing objects:  66% (4/6)
Compressing objects:  83% (5/6)
Compressing objects: 100% (6/6)
Compressing objects: 100% (6/6), done.
Writing objects:  14% (1/7)
Writing objects:  28% (2/7)
Writing objects:  42% (3/7)
Writing objects:  57% (4/7)
Writing objects:  71% (5/7)
Writing objects:  85% (6/7)
Writing objects: 100% (7/7)
Writing objects: 100% (7/7), 630 bytes | 630.00 KiB/s, done.
Total 7 (delta 1), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Resolving deltas:   0% (0/1)        
remote: Resolving deltas: 100% (1/1)        
remote: Resolving deltas: 100% (1/1), done.        
remote: 
remote: Create a pull request for 'feature' on GitHub by visiting:        
remote:      https://github.com/mcallara/my-project/pull/new/feature        
remote: 
To https://github.com/mcallara/my-project.git
 * [new branch]      feature -> feature
branch 'feature' set up to track 'origin/feature'.

Inner workings: remote refs

After pushing, if we inspect the .git/refs again we see that the remotes directory has been created and now contains a reference to the remote repository.

ls .git/refs
heads  remotes	tags
ls .git/refs/remotes

Listing branches and commits

git branch --all
  feature
* main
  remotes/origin/feature
  remotes/origin/main
git log
commit cf5639f09964baaf487c66420f818bf086074750 (HEAD -> main, origin/main)
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:14 2026 +0000

    Add third line to file1.txt

commit 06b6a5b53032d9eee4f2363ca6c6cfe818b04500
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:13 2026 +0000

    Add second line to file1.txt

commit 90fcf4335b70e4e5df2ed0b34a2adab1161a0360
Author: mcallara <msdp.book@gmail.com>
Date:   Wed May 13 14:09:12 2026 +0000

    Create file1.txt with the first line

Local and remote copies do not auto-sync

At this point, we have one project in two places: a local copy on your computer and a remote copy on Github. A key idea in Git is that these copies do not update each other automatically. They can diverge.

To make this visible, create a commit directly on Github (for example, edit file1.txt in the browser and click Commit changes). After that:

To bring your local copy up to date, run:

git pull origin main

If you are currently on main, this command does two things:

  1. It fetches main from origin and updates your remote-tracking reference (origin/main).

  2. It integrates those fetched commits into your current local branch (main).

By default, step 2 uses a merge strategy. In practice:

So git pull origin main is conceptually:

git fetch origin main
git merge FETCH_HEAD
git status
git log --oneline --decorate -n 5

Cloning a repository

Clone the my-project into a new directory named my-project-remote.

cd ..
git clone https://github.com/mcallara/my-project.git my-project-remote
ls
Cloning into 'my-project-remote'...
remote: Enumerating objects: 15, done.        
remote: Counting objects:   6% (1/15)        
remote: Counting objects:  13% (2/15)        
remote: Counting objects:  20% (3/15)        
remote: Counting objects:  26% (4/15)        
remote: Counting objects:  33% (5/15)        
remote: Counting objects:  40% (6/15)        
remote: Counting objects:  46% (7/15)        
remote: Counting objects:  53% (8/15)        
remote: Counting objects:  60% (9/15)        
remote: Counting objects:  66% (10/15)        
remote: Counting objects:  73% (11/15)        
remote: Counting objects:  80% (12/15)        
remote: Counting objects:  86% (13/15)        
remote: Counting objects:  93% (14/15)        
remote: Counting objects: 100% (15/15)        
remote: Counting objects: 100% (15/15), done.        
remote: Compressing objects:  11% (1/9)        
remote: Compressing objects:  22% (2/9)        
remote: Compressing objects:  33% (3/9)        
remote: Compressing objects:  44% (4/9)        
remote: Compressing objects:  55% (5/9)        
remote: Compressing objects:  66% (6/9)        
remote: Compressing objects:  77% (7/9)        
remote: Compressing objects:  88% (8/9)        
remote: Compressing objects: 100% (9/9)        
remote: Compressing objects: 100% (9/9), done.        
remote: Total 15 (delta 2), reused 14 (delta 1), pack-reused 0 (from 0)        
Receiving objects:   6% (1/15)
Receiving objects:  13% (2/15)
Receiving objects:  20% (3/15)
Receiving objects:  26% (4/15)
Receiving objects:  33% (5/15)
Receiving objects:  40% (6/15)
Receiving objects:  46% (7/15)
Receiving objects:  53% (8/15)
Receiving objects:  60% (9/15)
Receiving objects:  66% (10/15)
Receiving objects:  73% (11/15)
Receiving objects:  80% (12/15)
Receiving objects:  86% (13/15)
Receiving objects:  93% (14/15)
Receiving objects: 100% (15/15)
Receiving objects: 100% (15/15), done.
Resolving deltas:   0% (0/2)
Resolving deltas:  50% (1/2)
Resolving deltas: 100% (2/2)
Resolving deltas: 100% (2/2), done.
my-project  my-project-remote

Deleting a remote repository

To delete the remote repository in Github, navigate to the repository settings, scroll down to the Danger Zone section, and click on “Delete this repository”. You will be prompted to confirm the deletion by typing the repository name.