Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Fundamentals of Git

Git is a distributed version control system used to track changes in files and to manage the history of a software project.

In software engineering, Git allows us to:

  • create repositories;
  • track changes over time;
  • create checkpoints of development;
  • compare different states of a project;
  • create independent branches of development;
  • merge completed work;
  • undo changes;
  • inspect project history;
  • recover previous states;
  • temporarily store unfinished work;
  • mark important versions with tags.

Git is not only a tool for collaboration.

Even when you are working completely alone, Git gives you something extremely important:

A structured history of how your project changed.

That history allows you to experiment without constantly being afraid of destroying the previous working state.


Installing Git on Linux Mint

On Linux Mint, Git can be installed directly through APT:

sudo apt update
sudo apt install git

Verify the installation:

git --version

Display general Git help:

git help

Useful built-in help commands include:

git help -a
git help -g
git help init
git help commit
git help branch
git help merge

You can also use:

git <command> --help

For example:

git commit --help
git status --help
git log --help

Do not try to memorize every Git flag.

Learn the concepts first.

Then use Git’s own documentation when you need a specific option.


Initial Git Configuration

Before creating commits, configure the identity that Git will store in commit metadata.

Set your name:

git config --global user.name "Your Name"

Set your email:

git config --global user.email "you@example.com"

Inspect global configuration:

git config --global --list

Your global Git configuration is normally stored in:

~/.gitconfig

You can inspect it with:

cat ~/.gitconfig

or:

nano ~/.gitconfig

You normally do not need to create this file manually. Git creates or updates it when configuration values are written.


Creating a Working Directory

For the examples in this guide, create a directory that will contain Git repositories:

mkdir -p ~/gitLib
cd ~/gitLib

Now create the first project:

mkdir first_repo
cd first_repo

git init - Initialize a Repository

A normal directory is not automatically a Git repository.

To initialize Git inside the current directory:

git init

Example output may look similar to:

Initialized empty Git repository in /home/developer/gitLib/first_repo/.git/

Inspect hidden files:

ls -la

You will now see:

.git/

The .git directory contains Git’s repository metadata and object database.

That directory is what turns the project directory into a Git repository.

Do not manually edit or delete files inside .git unless you understand Git internals and know exactly what you are doing.


The Fundamental Git Cycle

A basic Git workflow looks like this:

Initialize repository
        ↓
Modify files
        ↓
Inspect status
        ↓
Stage selected changes
        ↓
Commit staged changes
        ↓
Inspect history
        ↓
Continue development

The most important commands at the beginning are:

git init
git status
git add
git commit
git log

Everything else builds on these concepts.


Working Tree, Staging Area, and Repository

Before going further, understand the three main states involved in normal Git work.

Working Tree
    ↓
Staging Area
    ↓
Repository History

The working tree contains the files you are currently editing.

The staging area contains the exact changes selected for the next commit.

The repository history contains commits that have already been recorded.

A useful mental model is:

edit
  ↓
git add
  ↓
stage
  ↓
git commit
  ↓
history

git status

Immediately after initialization:

git status

A new repository may report:

On branch master

No commits yet

nothing to commit

Depending on your Git configuration, the default branch may be named master or main.

This guide uses:

master

because that is the branch name used throughout the original Team413 material.

The Git concepts are identical regardless of the branch name.


Creating an Untracked File

Create a file:

touch message1.txt

Now inspect status:

git status

Git will report the file as untracked.

Conceptually:

message1.txt
    ↓
exists in working tree
    ↓
Git is not tracking it yet

git add - Add Changes to the Staging Area

Stage one file:

git add message1.txt

Inspect status:

git status

The file is now prepared for the next commit.

You can stage all current changes with:

git add .

But do not use git add . automatically without looking at what changed.

A better habit is:

git status
git diff
git add <specific-files>

when you want precise control over the next commit.


Removing a File From the Staging Area

The original guide demonstrates:

git rm --cached message1.txt

That command removes the file from Git’s index while leaving the working-tree file present.

For a file that you merely staged accidentally and still want Git to track later, modern Git also provides:

git restore --staged message1.txt

The important concept is:

Staging can be changed before committing.

A commit should contain the exact change you intend to record.


git commit - Create a Checkpoint

A commit records the staged state of the project.

Think of a commit as a checkpoint.

Stage the file:

git add message1.txt

Create the first commit:

git commit -m "Our first system message"

Git creates a commit with its own unique identifier.

Afterward:

git status

should show:

nothing to commit, working tree clean

The Three Common Change States

A tracked file may conceptually move through:

modified
    ↓
staged
    ↓
committed

Modified - The file differs from the last committed version.

Staged - The change has been selected for the next commit.

Committed - The staged change has been stored in repository history.


Short Status

Use:

git status -s

or:

git status --short

Typical status letters include:

??    untracked
M     modified
A     added
D     deleted
R     renamed

The short format is useful once you understand what the symbols represent.


git log - Commit History

Display commit history:

git log

A normal entry contains:

  • commit ID;
  • author;
  • timestamp;
  • commit message.

A compact view:

git log --oneline

Example:

0ef0242 Our first system message

The value:

0ef0242

is a shortened form of the commit ID.

Git commit IDs allow us to reference exact historical states.


Limiting Log Output

Show the last three commits:

git log -n 3 --oneline

Show commits between two revisions:

git log <older>..<newer> --oneline

Example:

git log d110129..74d91c --oneline

Visualizing History

A very useful command is:

git log --oneline --decorate --graph --all

This shows:

  • compact commit IDs;
  • branch and tag names;
  • branch relationships;
  • the commit graph.

Use this frequently while learning branches and merges.


Branches

A branch represents an independent line of development.

Branches allow us to isolate:

  • new features;
  • bug fixes;
  • experiments;
  • refactoring;
  • temporary work.

A common workflow is:

stable branch
      ↓
create feature branch
      ↓
develop and commit
      ↓
test
      ↓
merge
      ↓
remove feature branch when finished

Listing Branches

git branch

The active branch is marked with:

*

Example:

* master

Creating a Branch

git branch feature/task2

List again:

git branch

Example:

  feature/task2
* master

The branch exists, but we have not switched to it yet.


Switching Branches

The original guide uses:

git checkout feature/task2

Modern Git also provides:

git switch feature/task2

Both concepts mean:

Move HEAD to another branch and update the working tree to that branch’s state.


Create and Switch in One Command

Using checkout:

git checkout -b feature/task3

Modern equivalent:

git switch -c feature/task3

Rename a Branch

git branch -m old-name new-name

Example:

git branch -m small-feature quick-feature

Commit Changes on a Feature Branch

Switch to the feature branch:

git checkout feature/task2

Modify a file:

echo "This is the first system message!" >> message1.txt

Inspect:

git status

Stage:

git add message1.txt

Commit:

git commit -m "First system message has been modified"

Inspect history:

git log --oneline --decorate --graph --all

You should now see that the feature branch contains a commit that the original branch does not yet contain.


git diff Between Branches

Before merging, inspect the difference:

git diff master feature/task2

Git displays what changes would distinguish one branch state from the other.


Merging a Branch

To merge feature/task2 into master, first switch to the branch that should receive the changes:

git checkout master

Then:

git merge feature/task2

This direction matters.

Conceptually:

current branch
    +
incoming branch
    ↓
merged current branch

Fast-Forward Merge

If master has not changed since the feature branch was created, Git may perform a fast-forward merge.

Before:

A---B   master
     \
      C---D   feature

After fast-forward:

A---B---C---D   master, feature

Git does not need a new merge commit.

It simply moves the master branch pointer forward.


Deleting a Merged Branch

After a feature has been merged:

git branch -d feature/task2

The lowercase -d performs a safe deletion and refuses when the branch contains work that Git considers unmerged.

Force deletion:

git branch -D feature/task2

Use -D carefully. It can remove a branch that contains commits not reachable from another branch.


git commit -a

For already tracked files, Git can stage modifications and deletions as part of commit:

git commit -am "Fourth system message has been added"

This is effectively useful for tracked files only.

It does not automatically include brand-new untracked files.

For new files, use:

git add new-file
git commit -m "Add new file"

Creating Several Commits

Create another modification:

echo "Second system message: Welcome!" >> message1.txt
git add message1.txt
git commit -m "Second system message has been added"

Then another:

echo "Third system message: Analyze!" >> message1.txt
git add message1.txt
git commit -m "Third system message has been added"

And another:

echo "Fourth system message: Proceed!" >> message1.txt
git commit -am "Fourth system message has been added"

Inspect:

git log --oneline

Now the project history contains multiple checkpoints.


Checking Out a Specific Commit

Suppose the history contains:

e0c20e6 Fourth system message has been added
24af2fa Third system message has been added
aba3bd9 Second system message has been added
650bf2c First system message has been modified
0ef0242 Our first system message

To inspect the repository at the second-message commit:

git checkout aba3bd9

Git will enter a detached HEAD state.


Understanding HEAD

HEAD represents the currently checked-out position.

Normally:

HEAD
 ↓
branch
 ↓
commit

For example:

HEAD -> master -> e0c20e6

In detached HEAD state:

HEAD -> aba3bd9

HEAD points directly to a commit rather than to a normal branch.


Detached HEAD

Detached HEAD is useful for:

  • inspecting old states;
  • testing old commits;
  • temporary experiments;
  • comparing historical versions.

Example:

git status

may show:

HEAD detached at aba3bd9

The working tree now represents the selected historical commit.


Creating Commits in Detached HEAD

You can modify files and commit while detached.

For example:

echo "Experimental message" >> message1.txt
git commit -am "Experimental detached commit"

But that commit is not automatically attached to a normal branch.

If you later switch away, Git may warn that you are leaving the commit behind.

To preserve it, create a branch:

git branch experiment <commit-id>

or while currently detached:

git switch -c experiment

Creating a Branch From an Older Commit

Checkout the historical commit:

git checkout aba3bd9

Create a new branch from that point:

git checkout -b feature/task5

Now any new commits belong to feature/task5.

This is one of Git’s most powerful properties:

Any historical commit can become the starting point of a new line of development.


git revert - Safely Undo a Commit

Suppose the latest commit added something that should be removed.

Use:

git revert HEAD

Git creates a new commit that reverses the effect of the selected commit.

History remains intact.

Conceptually:

A---B---C
        ↓
   incorrect change

git revert C

A---B---C---D
            ↓
       inverse of C

Both the original commit and the revert remain visible.

This makes revert especially useful when history should remain traceable.


Revert a Specific Commit

git revert <commit-id>

Example:

git revert 140c7a6

git reset - Move Repository State

git reset is different from git revert.

Revert adds a new inverse commit.

Reset moves a branch reference and can change the staging area and working tree depending on the mode.

This makes reset powerful, but potentially destructive.


Unstage Changes With Reset

A plain:

git reset

moves staged changes out of the staging area while normally leaving the working-tree modifications present.

Conceptually:

staged
  ↓
git reset
  ↓
modified but unstaged

Modern Git also provides:

git restore --staged <file>

for explicit unstaging.


Reset to a Commit

git reset <commit-id>

By default this is a mixed reset.

The branch moves to the specified commit, while later file changes normally remain in the working tree as unstaged modifications.


git reset --hard

Example:

git reset --hard 24af2fa

This moves the branch and resets both:

  • staging area;
  • working tree.

Changes after the target state may disappear from the visible branch and working tree.

Treat git reset --hard as destructive. Always inspect git status and git log first.

Do not use it casually on work you have not protected.


Revert vs Reset

A simple comparison:

OperationHistoryWorking PrincipleTypical Use
git revertPreservedAdd inverse commitSafe history-preserving undo
git resetRepositionedMove branch/referenceLocal history manipulation
git reset --hardRepositionedMove branch and discard working/staged stateExplicit destructive reset

A useful rule:

Use revert when history should remain intact. Use reset when you intentionally want to rewrite or reposition local history.


git clean - Remove Untracked Files

git reset primarily affects tracked repository state.

git clean deals with untracked files.

Preview first:

git clean -n

or:

git clean --dry-run

This is extremely important.

It shows what Git would delete.


Remove Untracked Files

git clean -f

Remove untracked directories too:

git clean -df

Remove ignored files as well:

git clean -xf

git clean -xf is dangerous. It can delete build output, local configuration, generated data, and other ignored files.

Always run a dry-run variant first.


Merge With --no-ff

A normal fast-forward merge may not create a dedicated merge commit.

Sometimes you intentionally want the branch integration to remain visible in history.

Use:

git merge feature/task4 --no-ff

This forces a merge commit even when Git could fast-forward.

Example history:

*   Merge branch 'feature/task4'
|\
| * Feature commit 2
| * Feature commit 1
|/
* Previous master commit

This makes the existence of the feature branch explicit in the project history.


Fast-Forward vs --no-ff

Fast-forward:

A---B---C---D

Forced merge commit:

A---B-------M
     \     /
      C---D

Neither is universally correct.

The choice depends on how you want project history to communicate development structure.


Amend the Last Commit

Sometimes the last commit needs adjustment.

You may have:

  • forgotten to include a file;
  • written the wrong commit message;
  • staged one more correction immediately after committing.

Use:

git commit --amend

To replace only the message directly:

git commit --amend -m "Corrected commit message"

To add forgotten changes:

git add forgotten-file
git commit --amend

Important Property of Amend

Amending does not modify the existing commit in place.

It creates a new commit object with a new commit ID.

Conceptually:

old commit: 66ee579
        ↓ amend
new commit: 0229304

The visible history now points to the replacement commit.

This is history rewriting.

For local work, that is often fine.

Be careful when rewriting commits that other people may already depend on.


Rebase

Rebase rewrites one line of commits so that it appears to start from another base commit.

Suppose history looks like this:

A---B---C   master
     \
      D---E   feature

After rebasing feature onto master:

A---B---C---D'---E'   feature

D' and E' are new commits representing the replayed changes.

The original commit IDs change.


Why Rebase?

Rebase is often used to maintain a linear history.

Instead of creating:

A---B---C
     \   \
      D---E---M

you can replay feature work after the current base:

A---B---C---D'---E'

Basic Rebase

Switch to the feature branch:

git checkout feature/task5

Rebase onto master:

git rebase master

Git identifies commits that belong to the feature branch and replays them on top of the current master.


Rebase Can Produce Conflicts

If both histories changed overlapping parts of the same content, Git may stop with a conflict.

Example:

CONFLICT (content): Merge conflict in message1.txt

Inspect state:

git status

Open the conflicted file.

Git conflict markers may look like:

<<<<<<< HEAD
content from one side
=======
content from the other side
>>>>>>> commit

You must decide what the final content should be.


Resolve a Rebase Conflict

  1. Edit the conflicted file.
  2. Remove conflict markers.
  3. Keep the correct final content.
  4. Stage the resolved file.
git add message1.txt

Continue:

git rebase --continue

Abort a Rebase

If you want to return to the state before rebase started:

git rebase --abort

This is one of the most important rebase commands to remember.


Skip a Rebase Commit

Git also provides:

git rebase --skip

This skips the commit currently being replayed.

Use it only when you intentionally want to discard that commit’s change from the rebased history.


Rebase Conflict Principle

Editing the same file on different branches is completely normal.

A conflict does not happen merely because the same file changed.

Conflicts usually appear when Git cannot automatically reconcile overlapping changes.

For example:

branch A modifies line 20
branch B also modifies line 20

may require manual resolution.

While:

branch A modifies line 20
branch B modifies line 200

may merge or rebase automatically.

The important skill is not avoiding all concurrent edits.

The important skill is understanding how to resolve conflicting changes safely.


Rebase Changes Commit IDs

Because rebase creates new commit objects, commit IDs before and after rebase differ.

Before:

5ffabe2 Fifth system message
6224156 Sixth system message

After replay:

5e110cf Fifth system message
4aa3940 Sixth system message

The logical changes may be similar.

The commits are new objects.


Merge After Rebase

If a feature branch has been successfully rebased onto the current master, merging it may become a fast-forward:

git checkout master
git merge feature/task5

Then remove the completed branch:

git branch -d feature/task5

git reflog

Git’s normal log shows commits reachable through normal references.

reflog records how local references such as HEAD moved over time.

Run:

git reflog

Example entries may represent:

  • commits;
  • checkouts;
  • resets;
  • rebases;
  • branch switches.

Conceptually:

HEAD@{0}    current position
HEAD@{1}    previous movement
HEAD@{2}    movement before that

Why Reflog Matters

You may run:

git reset --hard <older-commit>

and think a newer local commit has disappeared.

But Git may still record the previous HEAD movement in reflog.

Inspect:

git reflog

Then inspect a previous state:

git show HEAD@{1}

or:

git checkout HEAD@{1}

A safer recovery approach is often to create a branch:

git branch recovery HEAD@{1}

Reflog Time Expressions

Git accepts several time expressions for reflog references.

Examples:

git show master@{1.hour.ago}
git show master@{1.day.ago}
git show master@{2.weeks.ago}

Display reflog-style history:

git log -g master

Reflog is local repository metadata.

It is an extremely useful recovery mechanism, but it should not be treated as a permanent backup system.


Tags

Tags mark important commits with meaningful names.

Typical uses include:

  • releases;
  • release candidates;
  • milestones;
  • stable checkpoints.

Example:

git tag v1.7-rc1

List tags:

git tag

or:

git tag --list

Show a Tag

git show v1.7-rc1

Git displays the commit associated with the tag and related information.


Lightweight Tags

A lightweight tag is essentially a name pointing directly to a commit.

Create one:

git tag v1.4-lw

Annotated Tags

Annotated tags create a tag object containing additional metadata.

Create:

git tag -a v1.4 -m "Version 1.4"

Annotated tags are useful when you want the tag itself to carry:

  • tagger information;
  • timestamp;
  • message.

Inspect Tag Object Type

Use:

git cat-file -t <tag>

Example:

git cat-file -t v1.4-lw

A lightweight tag commonly resolves directly to:

commit

An annotated tag resolves to:

tag

Find Tags

List matching tags:

git tag -l "v1.8*"

or:

git tag --list "v1.8*"

Describe Current State

git describe --all

Include tags:

git describe --all --tags

This is useful for connecting the current repository state to nearby named references.


Compare Tags

Tags can be used anywhere Git accepts revisions.

Example:

git diff v1.7-rc1 v1.8-rc2

This makes tags useful for release comparisons.


Move a Tag

Force a local tag to another commit:

git tag -f v3.1.0-beta <commit-id>

Delete a local tag:

git tag -d v3.1.0-beta

Be careful when moving meaningful release tags.

A tag is often treated as a stable reference.


Create a Branch From a Tag

git checkout -b branch-v1.8 v1.8-rc1

Modern equivalent:

git switch -c branch-v1.8 v1.8-rc1

This creates a new line of development from the tagged commit.


git stash

Sometimes you are in the middle of unfinished work and need to switch context.

You do not want to create a meaningless half-finished commit.

That is where stash is useful.

git stash temporarily stores uncommitted changes and restores the working tree toward the committed state.

Conceptually:

unfinished working changes
        ↓
git stash
        ↓
clean working tree
        ↓
do other work
        ↓
restore stash

Create a Stash

Modify a tracked file:

echo "For every connection we use SSL!" >> programming-language.txt

Then:

git stash

List stashes:

git stash list

Example:

stash@{0}: WIP on master: b854bf3 ...

Named Stash

A clear modern form is:

git stash push -m "database changes"

The original guide uses:

git stash save "database changes"

git stash save exists in older workflows, but git stash push -m is clearer for current Git usage.


Stash Indexing

Stashes are indexed:

stash@{0}
stash@{1}
stash@{2}

The newest stash is normally:

stash@{0}

If one is removed, the remaining indices may shift.

Do not assume an old index remains attached to the same stash forever.

Check:

git stash list

first.


Inspect a Stash

git stash show stash@{1}

Show a patch:

git stash show -p stash@{1}

Apply a Stash

Apply a specific stash without removing it from the stash list:

git stash apply stash@{1}

Apply the newest stash:

git stash apply

After application:

git status

will show the restored changes.


Pop a Stash

Apply and remove it:

git stash pop stash@{0}

Conceptually:

apply
+
drop

Drop a Stash

git stash drop stash@{1}

Delete all stashes:

git stash clear

git stash clear removes the entire stash stack. Check git stash list first.


Stash Untracked Files

By default, stash focuses on tracked modifications and staged changes.

Include untracked files:

git stash -u

or:

git stash push -u -m "work in progress"

Create a Branch From a Stash

Git can create a branch starting from the commit where the stash was originally created and apply the stash there:

git stash branch feature/task94 stash@{0}

This is useful when unfinished work has grown into something that deserves its own branch.


Stash Can Conflict

Applying a stash may conflict with changes already present in the current working tree.

For example:

error: Your local changes would be overwritten

At that point you may need to:

  • commit current changes;
  • stash current changes;
  • resolve overlaps manually;
  • reset only when you intentionally want to discard the current work.

Do not immediately use:

git reset --hard

unless you have confirmed that the current changes can be destroyed.


git diff

git diff compares Git data sources and displays differences.

It is commonly used together with:

git status
git log

Use git status to see what changed.

Use git diff to see how it changed.


Working-Tree Diff

Modify a file:

echo "New service for Payment!" >> programming-language.txt

Then:

git diff

Git displays the unstaged change.


List Changed Filenames

git diff --name-only

Example:

programming-language.txt

Short Statistics

git diff --shortstat

Example:

1 file changed, 1 insertion(+)

Name and Status

git diff --name-status

Possible status letters include:

LetterMeaning
AAdded
CCopied
DDeleted
MModified
RRenamed
TType changed
UUnmerged

Understanding Diff Output

A simplified Git diff may look like:

diff --git a/programming-language.txt b/programming-language.txt
--- a/programming-language.txt
+++ b/programming-language.txt
@@ -3,3 +3,4 @@
 We talk to each other via gRPC!
 We use only HTTP2 connection!
+New service for Payment!

Lines beginning with:

+

were added.

Lines beginning with:

-

were removed.


Compare Two Commits

Get commit IDs:

git log --oneline

Then:

git diff <commit-a> <commit-b>

Example:

git diff b854bf cff609

You usually do not need to type the entire commit hash as long as the shortened prefix is unique.


Compare a Commit With HEAD

git diff b854bf HEAD

HEAD represents the currently checked-out commit.


Compare Branches

git diff master feature/task94

For a specific file:

git diff master feature/task94 -- ./diff_test.txt

Using -- clearly separates revision arguments from file paths.


Two-Dot and Three-Dot Diff

Two branch tips can be compared with:

git diff branch1 branch2

or:

git diff branch1..branch2

A three-dot comparison:

git diff branch1...branch2

compares the common ancestor of the branches with the tip of the second branch.

This can be useful for asking:

What has branch2 changed since it diverged from branch1?


Compare Tags

git diff v1.7-rc1 v1.8.1

Because tags identify commits or tag objects resolving to commits, they are natural comparison points for releases.


Save a Diff to a File

Redirect output:

git diff b854bf HEAD > ~/diff-head-commit.txt

Inspect:

cat ~/diff-head-commit.txt

A diff can therefore be stored, reviewed, attached to documentation, or processed by other command-line tools.


A Complete Local Git Workflow

A practical local development cycle might look like:

git status

Modify files.

Then:

git diff

Stage selected changes:

git add file1 file2

Inspect staged state:

git status

Commit:

git commit -m "Implement feature X"

Create another line of development:

git checkout -b feature/y

Work and commit.

Then inspect:

git log --oneline --decorate --graph --all

Return:

git checkout master

Merge:

git merge feature/y

Delete completed branch:

git branch -d feature/y

This is already enough Git knowledge to work productively on a large amount of local software development.


Git Safety Rules

Git is extremely powerful because it allows history to be manipulated.

That is also why some commands require respect.

Before destructive operations, check:

git status
git log --oneline --decorate --graph --all

Before cleaning untracked files:

git clean -n

Before force-deleting a branch:

git log <branch>

Before:

git reset --hard

make sure the working-tree changes can actually be discarded.

Before:

git stash clear

inspect:

git stash list

The general rule is:

Inspect first. Modify second.


Commands You Should Know

At the end of this chapter, you should understand the purpose of:

git init
git config
git status
git add
git restore --staged
git commit
git log
git branch
git checkout
git switch
git merge
git diff
git revert
git reset
git clean
git commit --amend
git rebase
git reflog
git tag
git stash

You do not need to remember every flag.

You need to understand the state transitions they perform.


Git State Mental Model

A useful final model is:

Untracked File
      ↓ git add
Tracked / Staged
      ↓ git commit
Committed History

For an already tracked file:

Committed
    ↓ edit
Modified
    ↓ git add
Staged
    ↓ git commit
New Commit

Branches add another dimension:

                feature
               /
A---B---C------D---E
        \
         master

Merge combines development histories.

Rebase replays one history onto another base.

Revert adds a new commit that undoes an older one.

Reset moves references and can change staged or working state.

Stash temporarily stores unfinished work.

Reflog records local reference movement.

Tags give important commits meaningful names.

Diff explains the difference between states.

That is Git.


Final Perspective

Do not think of Git as a collection of commands.

Think of Git as a model of project history.

Every command changes one or more of these things:

working tree
staging area
commit history
branch references
HEAD
tags
stash

Once you understand those objects, Git stops feeling random.

You begin to understand why a command behaves the way it does.

The most important habit is not typing commands quickly.

It is being able to answer:

Where is HEAD?
Which branch am I on?
What is modified?
What is staged?
What is committed?
What history will this command change?
Can I recover if I make a mistake?

When you can answer those questions before executing a Git command, you are no longer memorizing Git.

You are using it deliberately.

Scalionix Docs

Keyboard Shortcuts

Navigate the documentation without leaving the keyboard.
Navigation
Previous subject
←
Next subject
→
Previous subsection
Alt + ↑
Next subsection
Alt + ↓
Interface
Documentation Home
Ctrl + Enter
Search
Alt + Q
Open shortcuts
?
Close dialog
Esc
Scalionix Docs

Search Documentation