Post

Git to Know

Unlike other version control system, which are delta-based version control, git thinks about its data more like a stream of snapshots.

Git has three main states that your file can reside in.

  • modified - you have changed the file but have not committed it to your database yet
  • staged - you have marked a modified file in its current version to go into your next commit snapshot
  • committed -data is safely stored in your local database

Installing Git

1
2
sudo apt install git-all # Debian-based distro
brew install git # MacBook

For other platform:Installation Guide

First-Time Git Setup

There are few things to consider after installation of Git. I would suggest you to go through Page 21, 22 and 23 of Pro Git book.

1
2
# Checking your settings
git config --list

Getting Help

1
2
3
4
5
6
git help <verb>
git <verb> --help
man git-<verb>

#Example
git help config

Git Basics

Initializing a repo

1
2
3
git init

git --version # Output git version 2.46.0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# Example of initializing git

# git init
macbook@MacMan Git-to-know % git init 
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint:   git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint:   git branch -m <name>
Initialized empty Git repository in /Users/macbook/Library/CloudStorage/OneDrive-Personal/Repos/Git-to-know/.git/

# list the files created
macbook@MacMan Git-to-know % ls -a
.               ..              .git            how-to-git.md

# changed the brach name to main
macbook@MacMan Git-to-know % git branch -m main

# checking the current git status
macbook@MacMan Git-to-know % git status
On branch main

No commits yet

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

nothing added to commit but untracked files present (use "git add" to track)
macbook@MacMan Git-to-know % 

On the above example I changed the branch name to main because GitHub changed the default branch name from master to main. However, Git itself still uses master as the default.

1
2
3
4
5
6
7
8
9
10
11
12
# Tracking new file - means staged
macbook@MacMan Git-to-know % git add how-to-git.md

# Check status - it is staged i.e tracked
macbook@MacMan Git-to-know % git status
On branch main

No commits yet

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

Cloning a repo

1
2
3
git clone https://github.com/satishkarki/satishkarki.github.io.git # uses https protocol

git:// or user@server:path/to/repo.git # uses SSH protocol, more on this later

git status

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Long status
macbook@MacMan Git-to-know % git status
On branch main

No commits yet

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

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:   how-to-git.md

# Short status
macbook@MacMan Git-to-know % git status -s
AM how-to-git.md

Ignoring Files

Setting up a .gitignore file for your new repository is a good idea so you don’t accidentally commit files that you don’t want in your repo.

GitHub maintains a fairly comprehensive list of good .gitignore file examples for dozens of projects and languages at https://github.com/github/gitignore if you want a starting point for your project.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Example of .gitignore file

# ignore all .a files
*.a

# but do track lib.a, even though you're ignoring .a files above
!lib.a

# only ignore the TODO file in the current directory, not subdir/TODO
/TODO

# ignore all files in any directory named build
build/

# ignore doc/notes.txt, but not doc/server/arch.txt
doc/*.txt

# ignore all .pdf files in the doc/ directory and any of its subdirectories
doc/**/*.pdf

Recording Changes to Repo

git diff

The git diff shows you the exact lines added and removed- the patch, as it were.

1
2
3
4
git diff
git diff --staged
git difftool # Git Diff is an External tool
git difftool --tool-help # To check what is available on your system

git commit

1
2
3
4
5
6
git commit # this will open an editor like vim, :q to quit (pro tip)

git commit -m "My First Commit" # using -m flag

git commit -a -m "Skipped Staging Area" # Skip Staging Area with -a flag

git rm

If you simply remove the file (rm file) from your working directory, it shows up under the “Changes not staged for commit” (that is, unstaged) area of your git status output:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# rm remove-me.md
macbook@MacMan Git-to-know % rm remove-me.md 

# git status
macbook@MacMan Git-to-know % git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   how-to-git.md
        new file:   remove-me.md

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   how-to-git.md
        deleted:    remove-me.md

Then, if you run git rm, it stages the file’s removal. The next time you commit, the file will be gone and no longer tracked. If you modified the file or had already added it to the staging area, you must force the removal with the -f option. This is a safety feature to prevent accidental removal of data that hasn’t yet been recorded in a snapshot and that can’t be recovered from Git.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# git rm remove-me.md
macbook@MacMan Git-to-know % git rm remove-me.md
rm 'remove-me.md'

# git status
macbook@MacMan Git-to-know % git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   how-to-git.md

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:   how-to-git.md

Moving files

1
git mv files_from files_to # It is same as mv command

Viewing Commit History

1
2
3
4
5
6
7
8
9
10
11
12
13
14
git log

git log -p -2 # or --patch shows the difference introduced in each commit, -2 to show only last two entries

git log --stat

git log --pretty=oneline # other options are short, full, fuller

git log --pretty=format:"%h - %an, %ar : %s"

git log -S function_name # takes a string and shows only those commits that changed the number of occurrences of that string

git log -- path/to/file #limit the log output to commits that introduced a change to those files

Examples:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# git log

macbook@MacMan Git-to-know % git log
commit ecb242d014e3961fcfe1458b0998fa757e554357 (HEAD -> main)
Author: MacBook <macbook@MacMan.local>
Date:   Sat Nov 29 00:28:44 2025 -0500

    Topic completed upto move files

commit f23f6c247af1fea63dcd5b169856d553bc2dc418
Author: MacBook <macbook@MacMan.local>
Date:   Fri Nov 28 23:52:10 2025 -0500

    second commit

commit 64562463561c54bee3adcef331ba018dbc69f11d #SHA-1 Checksum
Author: MacBook <macbook@MacMan.local>
Date:   Fri Nov 28 23:49:19 2025 -0500

    First Commit
1
2
3
4
5
6
7
8
9
10
11
# git log --stat -1

macbook@MacMan Git-to-know % git log --stat -1
commit ecb242d014e3961fcfe1458b0998fa757e554357 (HEAD -> main)
Author: MacBook <macbook@MacMan.local>
Date:   Sat Nov 29 00:28:44 2025 -0500

    Topic completed upto move files

 how-to-git.md | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)
1
2
3
4
5
6
# git log --pretty=oneline

macbook@MacMan Git-to-know % git log --pretty=oneline
ecb242d014e3961fcfe1458b0998fa757e554357 (HEAD -> main) Topic completed upto move files
f23f6c247af1fea63dcd5b169856d553bc2dc418 second commit
64562463561c54bee3adcef331ba018dbc69f11d First Commit
1
2
3
4
5
6
# git log --pretty=format:"%h - %an, %ar : %s"

macbook@MacMan Git-to-know % git log --pretty=format:"%h - %an, %ar : %s"
ecb242d - MacBook, 15 minutes ago : Topic completed upto move files
f23f6c2 - MacBook, 52 minutes ago : second commit
6456246 - MacBook, 55 minutes ago : First Commit

Undoing Things

1
git commit --amend # Amends changes to latest commit without creating new commit

Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Before git commit --amend
macbook@MacMan Git-to-know % git log --pretty=oneline

c17c8553c6831684b9dbed203a4b8243f1dcf904 (HEAD -> main) Topic added upto vewing commits
ecb242d014e3961fcfe1458b0998fa757e554357 Topic completed upto move files
f23f6c247af1fea63dcd5b169856d553bc2dc418 second commit
64562463561c54bee3adcef331ba018dbc69f11d First Commit

git commit --amend

# After git commit --amend
macbook@MacMan Git-to-know % git log --pretty=oneline

ad7d380894cf988c971561dd8f265f50422e53be (HEAD -> main) this is the commit after ammend
ecb242d014e3961fcfe1458b0998fa757e554357 Topic completed upto move files
f23f6c247af1fea63dcd5b169856d553bc2dc418 second commit
64562463561c54bee3adcef331ba018dbc69f11d First Commit

On the above example, if you check the checksum of the last commit, they are different, because amend doesn’t add to the last commit, new commit is created and it will act like the previous commit never happend.

Unstaging a Staged file

1
2
3
git reset HEAD <file>

git restore --staged <file> # same as reset, it was introduced in Git v2.23.0

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# both files are staged
macbook@MacMan Git-to-know % echo 'This is test to check undo staged file feature' > unstage-me.md
macbook@MacMan Git-to-know % git add *
macbook@MacMan Git-to-know % git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   how-to-git.md
        new file:   unstage-me.md

# git reset HEAD unstage-me.md

macbook@MacMan Git-to-know % git reset HEAD unstage-me.md 
macbook@MacMan Git-to-know % git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   how-to-git.md

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        unstage-me.md

Unmodifying a Modified File

1
2
git checkout -- <file>
git restore <file>

Working with Remotes

Until now, I only had local repo and I didn’t have a remote repo. So I went to GitHub and created the repo and pushed the code.

1
2
3
git remote add origin https://github.com/satishkarki/how-to-git.git

git push -u origin main

Showing your remotes

1
2
3
4
5
6
7
8
9
# git remote
macbook@MacMan Git-to-know % git remote
origin

# git remote -v
macbook@MacMan Git-to-know % git remote -v
origin  https://github.com/satishkarki/how-to-git.git (fetch)
origin  https://github.com/satishkarki/how-to-git.git (push)
macbook@MacMan Git-to-know % 

Adding remote repos

1
2
3
4
5
6
7
8
# git remote add <shortname> <URL>
git remote add pb https://github.com/johndoe/how-to-git.git

# git remote -v
origin https://github.com/satishkarki/how-to-git.git (fetch)
origin  https://github.com/satishkarki/how-to-git.git (push)
pb https://github.com/johndoe/how-to-git.git (fetch)
pb https://github.com/johndoe/how-to-git.git (push)

Fetching and Pulling

1
2
3
git fetch <remote> # It only downlaods the data to local repo, it doesn't automatically merge

git pull # it will merge

Pushing to remote

1
git push <remote> <branch> # git push origin main

Warning !!

If you and someone else cloned it and someone push it upstream before you. Your push will be rejected. You will have to fetch that upstream push and incorporate into your code to push.

Inspecting a remote

1
git remote show origin

Example

1
2
3
4
5
6
7
8
9
10
11
12
# git remote show origin
macbook@MacMan Git-to-know % git remote show origin
* remote origin
  Fetch URL: https://github.com/satishkarki/how-to-git.git
  Push  URL: https://github.com/satishkarki/how-to-git.git
  HEAD branch: main
  Remote branch:
    main tracked
  Local branch configured for 'git pull':
    main merges with remote main
  Local ref configured for 'git push':
    main pushes to main (up to date)

This command is helpful to tell you if you are on the master/main branch and you run git pull , it will automatically merge the remote’s master/main branch into the local one after it has been fetched.

Renaming and Removing Remotes

1
2
3
git remote rename pb paul

git remote remove paul

Git Tagging

This functionality is used to mark release points.

1
2
3
# Listing Tags
git tag
git tag -l "v2.0" # --list is also same

Creating Tags

1
2
3
git tag -a v1.0 -m "my version 1.0" # Annotated Tag
git tag v1.5-lw # LightWeight Tag
git tag -a v1.6 ecb242d # Tagging later
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Example

macbook@MacMan Git-to-know % git show v1.0
tag v1.0
Tagger: MacBook <macbook@MacMan.local>
Date:   Sat Nov 29 22:41:28 2025 -0500

my version 1.0

commit ff194fe35dccfba09af67b799526f52a5d1efd8d (HEAD -> main, tag: v1.0, origin/main)
Author: MacBook <macbook@MacMan.local>
Date:   Sat Nov 29 21:37:31 2025 -0500

    Beginning of git remote topic

# git log --pretty=online

macbook@MacMan Git-to-know % git log --pretty=oneline
ff194fe35dccfba09af67b799526f52a5d1efd8d (HEAD -> main, tag: v1.0, origin/main) Beginning of git remote topic
ad7d380894cf988c971561dd8f265f50422e53be this is the commit after ammend
ecb242d014e3961fcfe1458b0998fa757e554357 Topic completed upto move files
f23f6c247af1fea63dcd5b169856d553bc2dc418 second commit
64562463561c54bee3adcef331ba018dbc69f11d First Commit
1
2
3
4
5
6
7
8
# Lightweight tag

macbook@MacMan Git-to-know % git log --pretty=oneline
ff194fe35dccfba09af67b799526f52a5d1efd8d (HEAD -> main, tag: v1.5-lw, tag: v1.0, origin/main) Beginning of git remote topic
ad7d380894cf988c971561dd8f265f50422e53be this is the commit after ammend
ecb242d014e3961fcfe1458b0998fa757e554357 Topic completed upto move files
f23f6c247af1fea63dcd5b169856d553bc2dc418 second commit
64562463561c54bee3adcef331ba018dbc69f11d First Commit

Sharing Tags

1
2
3
git push origin <main> # git push origin v1.0
git push --tags # For multiple tags
git push <remote> --follow-tags # push only annotated tags

By default, the git push command doesn’t transfer tags to remote servers. There is currently no option to push only lightweight tags.

Deleting Tags

1
2
3
4
5
6
git tag -d <tagname>

git push <remote> :refs/tags/<tagname> 
# or
git push origin --delete <tagname>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Example

# Git log before tag deletion

macbook@MacMan Git-to-know % git log --pretty=oneline
ff194fe35dccfba09af67b799526f52a5d1efd8d (HEAD -> main, tag: v1.5-lw, tag: v1.0, origin/main) Beginning of git remote topic
ad7d380894cf988c971561dd8f265f50422e53be this is the commit after ammend
ecb242d014e3961fcfe1458b0998fa757e554357 Topic completed upto move files
f23f6c247af1fea63dcd5b169856d553bc2dc418 second commit
64562463561c54bee3adcef331ba018dbc69f11d First Commit

# Removing annotated tag
macbook@MacMan Git-to-know % git tag -d v1.0
Deleted tag 'v1.0' (was 321cc86)

# Removing lightweight tag
macbook@MacMan Git-to-know % git tag -d v1.5-lw
Deleted tag 'v1.5-lw' (was ff194fe)

# Git log after tag deletion
macbook@MacMan Git-to-know % git log --pretty=oneline
ff194fe35dccfba09af67b799526f52a5d1efd8d (HEAD -> main, origin/main) Beginning of git remote topic
ad7d380894cf988c971561dd8f265f50422e53be this is the commit after ammend
ecb242d014e3961fcfe1458b0998fa757e554357 Topic completed upto move files
f23f6c247af1fea63dcd5b169856d553bc2dc418 second commit
64562463561c54bee3adcef331ba018dbc69f11d First Commit

Tips!!

You can check out the tag as well. For this I would suggest check page 60 of Pro Git book.

Git Aliases

If you don’t want to type the entire command, you can setup alias using git config

1
2
3
4
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status

Example

1
2
3
4
git config --global alias.unstage 'reset HEAD --'
# This makes the following command equivalent
git unstage fileA
git reset HEAD -- fileA

At this point, you can do all the basic local Git operation. Next we will look at the Git’s killer feature: its branching model.

Reference

https://gitimmersion.com/lab_01.html

https://learngitbranching.js.org/

https://git-scm.com/book/en/v2

This post is licensed under CC BY 4.0 by the author.