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 --versiongit 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 --listuser.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 -aInitialize 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 mainInitialized empty Git repository in /home/runner/work/msdp-book/home/ch1/my-project/.git/
ls -a. .. .git
Check the repository status:
git statusOn 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 .gitAfter 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 mainInitialized 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).
The working directory is the area in which you create, edit and delete files.
The staging area, or index, is a file, stored in the
.gitdirectory, that stores information about what will go into your next commit.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.txtNow we have a file in the working directory. Let’s check the repository status using the git status command.
git statusOn 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.txtgit statusOn 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 statusOn branch main
nothing to commit, working tree clean
Listing the commits¶
We can list the commit history using the git log command.
git logcommit 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 logOutput
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 statusOn 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.
Open the Source Control Panel: In VSC, click on the Source Control icon on the sidebar or press
Ctrl+Shift+G(Cmd+Shift+Gon macOS) to open the Source Control panel.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.
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.
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.
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 pressCtrl+Enter(Cmd+Enteron macOS) to commit.
Checking how the branch pointer moves¶
Let’s check the commit history again to see how the branch pointer moves.
git logcommit 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 featureSource
git branchOutput
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 logOutput
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/headsfeature main
A file is created for each branch. Let’s look at the contents of the feature file.
cat .git/refs/heads/feature06b6a5b53032d9eee4f2363ca6c6cfe818b04500
The file contains the hash of the commit to which the branch is pointing.
cat .git/HEADref: refs/heads/main
The HEAD file contains the reference to the current branch.
Switching to the new branch¶
git switch featureSwitched to branch 'feature'
git branch* feature
main
git logcommit 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 logcommit 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: This merge strategy is used when the target branch can be updated to point to the commit of the source branch without needing to create a new commit.
Three-way merge: A three-way merge is used when the two branches have diverged and a new commit is required to reconcile the differences.
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 mainSwitched to branch 'main'
git merge featureUpdating 06b6a5b..cf5639f
Fast-forward
file1.txt | 1 +
1 file changed, 1 insertion(+)
git statusOn 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 logcommit 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.txtfile1.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 mainSwitched to branch 'main'
ls
cat file1.txtfile1.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.txtSwitched to branch 'feature'
git switch mainerror: 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
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.txtgit statusOn 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 -sMM 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.txtgit status -sM 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 logSwitched 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 --allAlready 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~2Note: 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 statusHEAD detached at cf5639f
nothing to commit, working tree clean
git log --allcommit 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-nameSwitched 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 statusOn 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-nameSwitched 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.gitList the remote repository connections¶
Git provides the remote command to list the remote repositories linked to your local repository.
git remoteorigin
With the -v option, you can see the URLs used for fetching and pushing data.
git remote -vorigin https://github.com/mcallara/my-project.git (fetch)
origin https://github.com/mcallara/my-project.git (push)
(fetch): This specifies the URL used for fetching data from the remote repository. Fetching involves downloading objects and refs from the remote repository to update your local repository’s history.(push): This indicates the URL used for pushing data to the remote repository. Pushing involves sending your local commits to the remote repository to update its history and potentially update branches on the remote.
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/refsheads 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 mainEnumerating 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 featureEnumerating 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/refsheads remotes tags
ls .git/refs/remotesListing branches and commits¶
git branch --all feature
* main
remotes/origin/feature
remotes/origin/main
git logcommit 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:
The remote copy has a new commit.
Your local copy is still at the previous commit.
To bring your local copy up to date, run:
git pull origin mainIf you are currently on main, this command does two things:
It fetches
mainfromoriginand updates your remote-tracking reference (origin/main).It integrates those fetched commits into your current local branch (
main).
By default, step 2 uses a merge strategy. In practice:
If your local
mainhas no unique commits, Git performs a fast-forward update.If local and remote have diverged, Git creates a merge commit (or asks you to resolve conflicts first).
So git pull origin main is conceptually:
git fetch origin main
git merge FETCH_HEADgit status
git log --oneline --decorate -n 5Cloning 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
lsCloning 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.