Complete Git Tutorial – All You Need to Get Started
This Git tutorial will take you through the essentials needed to get started with Git.
Git is a Distributed Version Control System (DVCS) used to save different versions of a file (or set of files)—wherein any version is retrievable at will.
Git makes it easy to record and compare different file versions. Consequently, details about what changed, who changed what, or who initiated an issue are reviewable anytime.
Git is not equivalent to GitHub.
Git is a version control system, while GitHub is a version control hosting service for hosting .git
repositories.
You can learn more about the differences between the two technologies in the Git vs. GitHub article.
What Is a Version Control System?
A Version Control System (VCS) refers to the specific technique employed to save a file's versions for future references.
Intuitively, many people already version control their projects by renaming different versions of the same file in various ways like blogScript.js
, blogScript_v2.js
, blogScript_v3.js
, blogScript_final.js
, blogScript_definite_final.js
, and so on. However, this approach is error-prone and ineffective for team projects.
Moreover, tracking what changed, who changed it, and why it got changed is a tedious endeavor. Thus, the importance of a reliable and collaborative version control system like Git.
What Git Is Not
Git is not a Local Version Control System (LVCS) that saves file changes in a unique format on a local hard disk—without any collaborative support.
It is also not a Central Version Control System (CVCS) that stores all its versioned files centrally on a single server.
A Central Version Control System supports collaboration.
What Git Is
Git is a Distributed Version Control System (DVCS) that allows clients to clone an entire project's repository onto their disk.
In other words, Git enables the storage and simultaneous manipulation of a file's versions on multiple servers (computers).
As such, if a server dies, the project's repository is still retrievable from another server that has a copy.
Additionally, many DVCS—including Git—have remote repositories (an online folder) that foster collaborative work on projects with anyone, anywhere, anytime.
What Does "distributed" Mean in Git?
In Git, "distributed" means a project's entire content gets distributed whenever you share its .git
repository.
In other words, whoever a project's .git
repository gets distributed to will get all the files, commits, and branches in that repository.
Git's "distributed" system is in sharp contrast to other version control systems.
Git distributes by sharing everything inside the repository it is tracking.
However, virtually all other VCS only share the specific file version a user has explicitly checked out from the central/local database.
What Is a Remote Repository?
A remote repository refers to a duplicated copy of a project's .git
repository hosted elsewhere—be it on the internet, a network somewhere else, or on a different location on your computer.
Remote vs. Local Repositories
Remote repositories are like any local directory—in that, they are just folders.
The main difference between the two repositories is that only the person with the system can access a local repository.
However, a remote repository—located on an open platform like the internet—is accessible by anyone, anywhere, anytime.
As such, remote repositories facilitate dynamic collaboration on projects.
- The term "remote" means "elsewhere"—not "online". Therefore, a
.git
directory duplicated to a location "elsewhere" on your local system is still a remote repository. Moreover, regardless of the type of remote repository, all the standardpush
,pull
,fetch
operations are still applicable. - The Git local repository—automatically named
.git
—is a hidden folder wherein Git stores all recorded versions of your project's file(s).
Files States in Git
The three primary states (conditions) a file can be in are: modified, staged, or committed.
Modified state
A file in the modified state is a revised—but uncommitted (unrecorded)—file.
In other words, files in the modified state are files you have modified but have not explicitly instructed Git to monitor.
Staged state
A staged file is a modified file you have selected in its current state (version) in preparation for being saved (committed) into the .git
repository during the next commit snapshot.
Once you stage a file, it implies that you have explicitly authorized Git to monitor that file's version.
Committed state
Files in the committed state are files successfully stored into the .git
repository.
In other words, a committed file is a file in which you have recorded its staged version into the .git
directory (folder).
The state of a file determines the location Git will place it.
Files Location
There are three key places versions of a file may reside while version controlling with Git: the working directory, the staging area, or the .git
directory.
Working directory
The working directory is a local folder for a project's files.
As such, any folder you create anywhere on a system is a working directory.
- Files in the modified state reside in the working directory.
- The working directory is different from the
.git
directory. You create a working directory while Git creates a.git
directory. - Find out more about the differences between a working directory and a Git directory in the Git vs. Working Directory article.
Staging area
The staging area is a file Git uses to store details about files it is about to commit into the .git
directory.
- Files in the staged state reside in the staging area.
- The staging area is technically called "index" in Git parlance.
- The staging area is usually in the
.git
directory.
Git directory
The .git
directory is the folder Git creates inside the working directory you have instructed it to track.
The .git
folder is where Git stores the object databases and metadata of the file(s) you have instructed it to monitor.
- The
.git
directory is the life of Git—it is the item copied when you clone a repository from another computer (or an online platform like GitHub). - Files in the committed state reside in the Git directory.
- A repository is another name for a folder.
The Basic Git Workflow
Working with the Git Version Control System looks something like this:
Step 1
Modify files in the working directory.
Any file you alter becomes a file in the modified state.
Step 2
Selectively stage the files you want to commit to the .git
directory.
- Any file you stage (add) into the staging area becomes a file in the staged state.
- Staged files are not yet in the
.git
database. - Staging puts information about the staged file in a file (called "index") located inside the
.git
repository.
Step 3
Commit the file(s) you have staged into the .git
directory.
In other words, permanently store a snapshot of the staged file(s) into the .git
database.
Any file version you commit to the .git
directory becomes a file in the committed state.
So, now that we know what Git is, we can discuss how to use it.
How to Use Git
Before you can use Git, you need to install it on your system—so let's start with the installation process.
How to Install Git
You can easily install Git from the Git download webpage.
A handy way to check the version installed on your system is to run:
git --version
After the installation, it is necessary to keep it up to date whenever there is a new version.
How to Update Git
If you are using a Windows system and your currently installed version is 2.16.1(2) or higher; freely get the latest version with this command:
git update-git-for-windows
Once you have the correct version installed on your system, you can then proceed with the setup process by initializing Git in your project's directory.
How to Initialize Git
Initialization is to make Git ready to start monitoring files in a specified directory.
To initialize Git in a directory currently not under version control, you need first to go inside that directory from your terminal.
cd path/to/the/directory
Afterward, initialize Git in that project's directory by running:
git init
After running the command above, a Git repository, named .git
, will be created in the project's folder.
- Initializing Git in a project does not mean Git is tracking anything in that project's directory. The
git init
command just creates the.git
repository where almost everything that Git stores and manipulates lives. - If you are curious about the contents in the
.git
directory, check Plumbing and Porcelain for more info.
How to Configure Git
After the installation and initialization process, it is essential to configure your username and email address—as Git permanently bakes these details into your commits. Thus, helping team members identify each commit's creator.
To configure your identity, run the following commands—one by one—in your terminal:
git config --global user.name "Your Name"
git config --global user.email "your-email@address.com"
The --global
option enables you to run the above commands only once. However, if you do not mind inputting your name and email for each project, you can omit the --global
flag.
How to Change a Project's Configuration
Suppose you need to change the configured name or email address for a specific project, go into that project's directory and run the command(s) below—one after the other:
git config user.name "The New Name"
git config user.email "the-new-email@address.com"
How to Check Your Project's Configuration
You can see all your project's configurations by running:
git config --list
Suppose you wish to confirm the value stored for a single configuration (for instance, your email). In such a case, use the git config <key>
command like so:
git config user.email
How to Exit the Git Configuration Space
To exit the Git configuration space, press the Q key on your computer's keyboard.
How to Track Your Files with Git
Once you've initialized and configured Git in a specific working directory, you can begin to use Git to track changes in your choice file(s). But the file(s) to be monitored must be in the working directory in which you initialized Git.
To begin tracking file(s) in the initialized project's folder, go into that project's directory from the terminal and run:
git add <fileOrFolderName>
After running the command above, Git will add the specified file (or folder) to the staging area.
- Once Git adds a file (or folder) to its staging area, it means Git has started monitoring that file's version for further modifications that may occur on it.
- Replace
<fileOrFolderName>
in the tracking command above with the file's (or directory's) pathname. - Suppose
<fileOrFolderName>
is the pathname of a directory. In that case, thegit add
command will automatically add all the files in that directory into the staging area recursively.
How to Stage Quickly
You can attach additional options to the git add
command to help speed up the staging process—especially when there are multiple files to stage.
Below are options commonly used to quicken the process of adding multiple files to the staging area.
Option 1: -A
Flag
Use the -A
flag to stage all modified and untracked files in a project's entire working directory—regardless of the current project's directory in which you are.
git add -A
The -A
flag used above is the shorthand notation for the --all
flag. You can use any one of the two flags to add all modified files to the staging area.
Option 2: -u
Flag
Use the -u
flag to stage only modified files that you committed previously.
git add -u
- The
-u
flag will stage all modified files—currently being track—in the project's entire working directory. This staging will occur regardless of the project's folder you are in presently. -u
flag will not add any new file (that is, previously uncommitted files) to the staging area.- The
-u
flag is the shorthand notation for the--update
flag. You can use any one of the two flags to update all modified files currently under version control.
Option 3: .
(dot) Symbol
Use the .
(dot) flag to stage all modified and untracked files located only in the current project's directory in which you are.
git add .
- A dot symbol means "current directory". As such, the above command will stage all modified, and untracked files only of that project's directory wherein the
git add .
command got invoked. - The dot is essential in the
add
command above. - There must be a space between the
add
command and the dot mark.
Option 4: *
(asterisk) Symbol
Technically, you can use the git add *
command also to stage multiple files. However, to prevent unexpected results, it is best to avoid using it.
Important Stuff to Know about Staging in Git
Keep these two essential pieces of info in mind whenever you stage files in Git.
Info 1: Staging does not save your files
Whenever you stage your files, it does not imply saving them into the Git directory.
Staging implies that you have added details about your staged file(s) into a file called "index"—located in the Git directory.
Info 2: Git commits staged files only
Only the file versions in the staging area get committed to subsequent historic snapshots—not the working directory's versions.
In other words, whenever you run the commit command, Git will only save the file versions presently in the staging area—not the versions in your working directory.
How to Commit Files to Git
Whenever you commit your files to Git, it means you have stored the staged version of your working directory's file(s) into the .git
repository.
To commit a file that is currently in the staging area, run:
git commit -m "Write a message about the file(s) you are committing"
Important Stuff to Know about Committing Files to Git
Keep these six essential pieces of info in mind whenever you commit files to Git.
Info 1: The -m
flag is optional
The -m
flag allows you to write your message in-line with the commit
command. If you omit it, your text editor will be launched with comments prompting you to enter your commit message.
In such a case, you can delete the editor's comments and type in your commit message. Or you can leave the comments and add your commit message.
Once you've finished writing your commit message inside the text editor, exit it so that Git can create the commit.
Writing commit messages with a text editor provides the opportunity to write long notes—even with multiple paragraphs. However, for short commit messages, the in-line method is sufficient.
Info 2: Use the -v
flag to see the changes you are about to commit
Suppose you prefer to use the text editor to input your commit message. In that case, add the -v flag to the git commit command like so:
git commit -v
By doing so, Git will include the diff of your changes into the editor so that you can see the exact changes you are about to commit.
In other words, use the -v
flag to include—at the bottom of the text editor's commit message template—the differences between what you are currently committing and your previous commit.
The diff at the bottom of your text editor's commit message template will not get included in your final commit message. Instead, it is only present to help you remember the changes you are about to commit—thereby making it easier to craft a good commit message.
Info 3: It pays to draft a good commit message
Crafting a good commit message will help your collaborators (and yourself—after some time) understand why you committed a specific version of your project's file(s).
Additionally, it will help elucidate differences that exist between the file versions committed.
Info 4: Where does Git store committed files?
Committed files reside in the local Git repository—named .git
. You can find this directory inside the root of your project folders in which you've initialized Git.
Info 5: How to view your project's commit history
You can view your project's commit history by running:
git log
The project's directory—whose commit history you want to check—must be the current directory.
Info 6: How to commit without staging first
Suppose you wish to commit your changes without staging them first. In such a case, you can skip the staging area (that is, omit running the git add
command) by adding an -a
flag to your git commit
like so:
git commit -a
By so doing, Git will automatically stage all the files it is already tracking. After the automatic staging, it will then commit the files.
How to Clone a Git Repository
Git Cloning is mainly about getting (downloading) a copy of a .git
repository.
For instance, you may need a copy of a project you intend to modify. In such a case, getting a clone of the project's .git
directory puts at your possession all the file versions the project's contributor(s) have committed to the .git
repository.
To clone a repository, run:
git clone <theGitRepoURL> <state the place to put the cloned git folder>
By so doing, Git will download a copy of the specified .git
repository into the place you've identified.
- Replace
<theGitRepoURL>
with the URL of the.git
directory you want to clone. - Substitute
<state the place to put the cloned git folder>
with your system's location, wherein you want the cloned.git
repository to reside. (If omitted, Git will use your current directory as the default clone location.) - Whenever you clone any remote repo, Git automatically names that repo's URL "
origin
". However, you can specify a different name with thegit clone -o yourPreferredName
command.
How to Tell Git to Ignore Specific Files
Suppose you do not want Git to monitor specific files or folders—including not listing them as untracked. In such a case, you can create a .gitignore
file.
A common practice is to create the .gitignore
file in a project's root directory.
How to Create a .gitignore
File
To create a .gitignore
file, go into the root directory wherein the file(s) you want to ignore are. Then, run the command below on your terminal:
touch .gitignore
How to Specify the Files You Want Git to Ignore
After creating a .gitignore
file in your project's root directory, open the .gitignore
file and write in it, the names of the file(s), folder(s), or filetype(s) you want Git to ignore.
You can use the hash symbol (#
) to include comments inside your .gitignore
file.
Example of a .gitignore
File
Here is an example of a .gitignore
file:
# In a ".gitignore" file, an asterisk (\*) is a wildcard symbol that
# means zero or more characters—but not a slash (/)—can replace
# the asterisk.
# The command below will ignore any document starting with "abc"
# located anywhere in this project:
abc*
# The command below will ignore all ".txt" filetypes located anywhere
# in this project:
*.txt
# In a ".gitignore" file, an exclamation mark (!) means "important".
# The command below will track "readme.txt" filetypes, even though
# you've instructed Git—through the asterisk command above—to
# ignore all ".txt" files:
!readme.txt
# The command below will ignore any "package-lock.json" file located
# anywhere in this project:
package-lock.json
# The command below will ignore only the "passwords.text" file
# located in the specified directory:
directory/of/passwords.text
# This command below will only ignore the "NOTE" file in the current
# directory—not in any other directory—of this project:
/NOTE
# The following command will ignore all the content inside any folder
# named "modules":
modules/
# This command below will ignore all ".txt" files directly inside the
# folder named "mix":
mix/*.txt
# Note that the command above will still track all ".txt" files that
# are in the subdirectories of the "mix" folder. For instance, it
# will ignore "mix/test.txt" but will track "mix/real/test.txt".
# In a ".gitignore" file, double asterisks (\*\*) mark—followed by a
# slash (e.g., \*\*/)—is a wildcard symbol that means zero or more
# directories' names can replace the double asterisks.
# The command below will ignore all ".pdf" files inside both the
# folder named "doc" and in any of its subdirectories:
doc/**/*.pdf
# The question mark (?) in the command below means any single
# character—except a slash—can replace the question mark:
sea?.txt
# As such, the command above will ignore files like "seas.txt" or
# "seat.txt". However, it will not ignore files like "seats.txt".
# In a ".gitignore" file, a pair of square brackets "[...]" specifies
# the range of characters acceptable for a single character position.
# Below are some examples.
# The command below means the character after character "n" can
# either be character "s" or character "t":
plan[st].js
# Therefore, the command above will match files like "plans.js" or
# "plant.js". But it will not match "plane.js" nor "plants".
# The command below means the character after character "n" can be
# any character between numbers "3 to 9" inclusive:
plan[3-9].js
# Therefore, the command above will match files like "plan3.js" or
# "plan5.js". But it will not match "plan10.txt" nor "plan1".
# The following command means the character after character "n" can
# be any character between letters "f to z" inclusive:
plan[f-z].js
# As such, the command above will match files like "plank.js" or
# "plany.js". But it will not match "plan2.txt" nor "plane".
# An exclamation mark within a square bracket "[!]" means "negate".
# The command below means the character after character "n" cannot be
# character "s" nor character "t":
plan[!st].js
# Therefore, the command above will match files like "plane.js" or
# "plan2.js". But it will not match "plans.js" nor "plant".
A .gitignore
file serves to ensure files that are currently untracked remain untracked.
In other words, Git won't ignore any file it is already tracking—even if specified in a .gitignore
file—unless you delete such a file from the staging area.
How to Manage Git Branches
Git branching provides a helpful way to create a subsection of your main work.
In other words, Git branch allows you to try new experiments on a secondary line of development without affecting your main work.
Let's see examples of how to manage Git branches.
How to Create, Rename, and Delete Git Branches
The sections below will examine how to use the git branch
command to create, rename, or delete your project's branches.
How to check the branches in a project's local Git repository
git branch
The command above will display all the branches in your local Git repository.
Alternatively, you can also use:
git branch --list
Note that Git will mark the current branch with an asterisk (*
).
How to check the branches in a project's remote Git repository
git branch -a
The command above will display all the branches in your remote Git repository.
How to create a new Git branch
git branch new-branch-name
The code above will create a new branch called new-branch-name
.
By default, Git creates a new branch from the HEAD point. However, you can specify the exact branch from which you want to create your new branch.
For instance, the command below tells Git to create new-branch-name
from existing-branch-name
.
git branch new-branch-name existing-branch-name
Keep in mind that you can also create a new branch from a specific commit like so:
git branch new-branch-name 7b804hrw
The code above instructs Git to create new-branch-name
from the commit with the hash number of 7b804hrw
.
- When you use the
git branch
command to create a new branch, Git will not automatically switch theHEAD
pointer to the new branch. You need to use thegit checkout
command to switch branches. - Git uses the
HEAD
pointer to reference the currently active local branch. In other words, aHEAD
branch is your currently checked-out local Git branch.
How to delete a specific Git branch
git branch -d branch-to-delete
The code above will delete the branch called branch-to-delete
.
Keep in mind that you cannot delete the branch that is currently the HEAD branch.
Likewise, Git does not permit deleting a branch that contains any unmerged changes.
If you really want to delete a branch with unmerged alterations, change the lowercase -d
flag to uppercase like so:
git branch -D branch-to-delete
How to rename the HEAD branch
git branch -m branch-new-name
The code above will rename the HEAD (active) branch to branch-new-name
.
How to rename a non-HEAD branch
git branch -m branch-old-name branch-new-name
The code above will rename branch-old-name
to branch-new-name
.
How to Switch between Git Branches
You can use either the checkout
or switch
command to switch between different versions of your project's branches.
Git Checkout vs. Switch – What's the Difference?
git checkout
is a versatile command that you can use to do many things, such as switching between branches, restoring files, and switching between commits.
However, you can use git switch
only to switch your project's HEAD from one branch to another.
Below are popular ways of using git checkout
and git switch
to switch between branches.
How to switch from one branch to another
git checkout branch-name
The command above instructs Git to switch to branch-name
.
Alternatively, you can also switch branches like so:
git switch branch-name
- After the switch,
branch-name
will become the HEAD (active) branch. In other words, the HEAD pointer will move tobranch-name
. - Use the
git reflog
command to see your HEAD pointer's history.
Suppose you switched from branch A to branch B, you can use the previous branch shorthand (-
) to switch back to branch A:
git switch -
How to create and switch immediately to a new branch
git checkout -b new-branch-name
The switch command equivalence of the code above is:
git switch -c new-branch-name
Note that the -b
and -c
flags tell Git to create a branch first before switching to it.
In other words, git checkout -b new-branch-name
is a shorthand for:
git branch new-branch-name
git checkout new-branch-name
While git switch -c new-branch-name
is a shorthand for:
git branch new-branch-name
git switch new-branch-name
By default, Git creates a new branch from the HEAD point. However, you can specify the exact branch from which you want to create your new branch.
For instance, the command below tells Git to create new-branch-name
from existing-branch-name
.
git checkout -b new-branch-name existing-branch-name
Here is the switch alternative:
git switch -c new-branch-name existing-branch-name
Keep in mind that you can also create a new branch from a specific commit like so:
git checkout -b new-branch-name 7b804hrw
The code above instructs Git to create new-branch-name
from the commit with the hash number of 7b804hrw
.
Here's the switch equivalence:
git switch -c new-branch-name 7b804hrw
How to Switch between Git Commits
You can use the git checkout
command to switch from one commit history to another.
By default, Git will only allow you to switch to another commit if you have committed all your changes.
Here's an example:
git checkout z8d2f115010634ea4ae0a2670p7aec61b394c306
The code above tells Git to switch to the commit having a hash string of z8d2f115010634ea4ae0a2670p7aec61b394c306
.
A commit hash is a long string that follows the word "commit" in a git log
command's output.
In other words, whenever you run the git log
command, you will get an output like so:
commit z8d2f115010634ea4ae0a2670p7aec61b394c306
Author: Oluwatobi Sofela <contact@codesweetly.com>
Date: Tue Dec 21 12:51:07 2021 +0100
Initialize project
The long string that follows the word "commit" in the snippet above is the commit hash.
"SHA-1 checksum" or "Git commit reference" are other names people call the commit hash.
Suppose you only wish to restore an old version of a specific commit's file. In such a case, indicate the file after the commit's hash like so:
git checkout z8d2f1 App.js
The code above tells Git to restore just the z8d2f1
's version of App.js
—not all z8d2f1
's commits.
- Whenever you switch to a commit, the HEAD pointer gets detached from the branch it was previously on and moves to the commit history you switched to. In other words, whenever you checkout a commit, the project's HEAD pointer switches to a "detached" state.
- Any changes you commit in the detached state will not get tracked by any branch. As such, you will have no way to reference the commits.
- The detached state is best for reviewing old commits—not for working.
- Suppose you wish to retain the changes you made while in the detached state. In that case, create a new branch from the commit with the
git checkout -b new-branch-name
command.
Keep in mind that you can exit the detached state by switching to any of your project's branches.
Here's an example:
git checkout main
The code above tells Git to switch to the main
branch.
How to Merge Git Branches
Git merging allows you to merge another branch's changes into the HEAD (current) branch.
Before invoking the merge command, ensure the active branch is the branch you want to merge into.
In other words, switch to the branch you wish to update before running the merge command.
Here's its syntax:
git merge name-of-branch-containing-your-changes
The code above instructs Git to merge name-of-branch-containing-your-changes
with the HEAD (current) branch.
Git may prompt you to enter a commit message on running the merge command. You can either provide a new message or accept Git's default.
Afterward, simply close the editor's window to save the commit message.
An alternate way to merge changes from one branch into the HEAD branch is to use the rebase command like so:
git rebase name-of-branch-containing-your-changes
- Beginners should avoid the rebase command as
git rebase
re-writes a project's history whilegit merge
doesn't. - See the merging vs. rebasing article on Bitbucket for more on the differences between
git merge
andgit rebase
.
How to Compare Git Branches
You can compare one branch with another like so:
git log first-branch-name..second-branch-name
The code above tells Git to compare first-branch-name
with second-branch-name
.
Therefore, Git will log out the commits present in second-branch-name
but not in first-branch-name
.
Other Git Commands You Will Find Useful
Below are other Git commands you will find handy.
How to check the status of your files
git status
How to check where Git got installed on your system
Here's how to check where Git got installed on your computer:
which git
How to compare the file version in the staging area with the most recent version committed into the Git directory
git diff --staged
The command above will show the difference between file version(s) in the staging area and the version(s) most recently committed to the Git directory.
How to compare the version of files in the working directory with the version you added to the staging area
git diff
- The
git diff
command shows the changes in a working directory's files that you've not yet staged. - By default,
git diff
will compare a working directory's file version with the version in the staging area. However, for any file currently not in the staging area,git diff
will compare the working directory's version with the last committed version. - Suppose nothing shows after running the
diff
command above. In that case, it implies that there is the same version of files in the working directory and the staging area. - The
git diff
command does not show the entire content of a file. Instead, it displays only the chunks. - To make the chunk less cumbersome, add the
--color-words
flag to thegit diff
command (that is,git diff --color-words
). Thus, each chunk will include just the modified words—not lines—and their context.
How to confirm if a specific file or folder is in the .git
directory
git ls-files | grep <fileOrFolderName>
- Replace
<fileOrFolderName>
in the command above with the name of the file (or directory) you want to check. - If nothing shows after running the command above, it means the specified file (or folder) is not in the
.git
directory. - The
grep
command is a useful utility for searching for a specified pattern or characters and printing lines that match that pattern. For instance,git ls-files | grep test.js
will look for and print lines that matchtest.js
. - Check Git's grep documentation for additional options for the grep command.
How to delete a file from the working directory and the .git
repository:
Use the following code to delete a file from your system and to stop Git from tracking the file.
git rm fileToDelete
- Suppose you only run
rm fileToDelete
—that is, excluding thegit
command. In such a case, the specified file will only get deleted from the working directory. Therefore, Git will still track it as an unstaged change.
However, running git rm fileToDelete
will delete the specified file from the working directory and automatically stage the removal.
As such, during the next commit, Git will delete the file from the .git
directory.
- Use the
-f
flag to forcefully remove modified files (or files previously added to the staging area). For instance,git rm -f fileToDelete
. - Use the
-r
flag to remove a folder. For instance, git rm -r folderToDelete.
How to open gitignore's manual page
git help gitignore
The gitignore manual will open in your default browser.
How to remove a file only from the staging area and not from your working directory:
Use the following code to stop Git from tracking a staged file.
git rm --cached fileToDelete
Use the -r
flag to stop tracking a staged folder. For instance, git rm --cached -r folderToDelete
.
How to rename a file
Here's how to rename a file:
git mv currentFileName newFileName
How to see all the files currently in the staging area and in the .git
repository
git ls-files
Additional options for the ls-files
command are listed in Git's ls-files documentation.
How to see your project's commit history
git log
- After running the command above, if you get stuck on the Git console, just hit the Q key on your keyboard to exit.
- Suppose you wish to limit the number of commit histories displayed to the last three entries, add
-3
to thegit log
command. For instance,git log -3
. - A
git log
command will display only basic commit history details—such as the author, date, and commit message. However, if you also wish to include the diff introduced in each of the commits, add-p
(short for--patch
) to thegit log
command. For instance,git log -2 -p
. - You can make the
git log
's output less cumbersome by adding the--color-words
flag—for instance,git log -p -2 --color-words
. As a result of such addition, each chunk will include just the modified words—not lines—and their context. - To display a summarized statistic of the changes that occurred in each commit, add the
--stat
flag to thegit log
command. For instance,git log --stat
. - See additional
git log
options in Git's "Viewing the Commit History" article.
How to skip writing a commit message
Suppose you made only minor modifications to your file, and you prefer not to write a commit message. In such a case, you can skip writing the commit text by adding the --no-edit
option to your git commit
command like so:
git commit --amend --no-edit
How to stage and commit at once
Here's how you can stage and commit your file at once:
git add <fileOrFolderName> && git commit -m "A message about your commit"
How to undo a commit
Suppose you wish to undo a specific commit. In such a case, run:
git revert <commit-to-undo>
The snippet above tells Git to create a new commit that reverts the changes introduced in <commit-to-undo>
.
- The
git revert
command does not delete any data. Instead, it creates a new commit that reverses the changes added to the specified commit. - After committing the reverted changes, the HEAD pointer will move to the new commit.
- In the snippet above, replace
<commit-to-undo>
with the commit you wish to undo—for instance,git revert b91ey04
. - Use a
--no-commit
(or-n
) flag to stop Git's default behavior of automatically committing the reverted changes. Instead, the--no-commit
flag puts the inverted changes in your working directory for you to edit further and commit manually. - Suppose you wish to use
git revert
's default commit message. In that case, add the--no-edit
flag to the command—for instance,git revert b91ey04 --no-edit
. By so doing, Git will not prompt you to provide a commit message for the reverted commit.
How to undo the pushing of a commit upstream
You can undo a commit you've recently pushed to a remote repository by running:
git revert HEAD
git push origin main
The snippet above tells Git to do the following:
- Create a new commit that reverts the changes made in the HEAD commit (that is, the recent commit).
- Push the local branch (named
main
) to the remote branch (origin
).
How to undo the staging of a specific file in the staging area
Here's how to remove a specific file from your project's staging area:
git reset HEAD fileToUnstage
The command above can be dangerous if you add a --hard
flag.
However, using git reset
without the --hard
flag makes it a non-destructive tool that would not change any file in your working directory.
Alternatively, you can also use:
git restore --staged fileToUnstage
How to undo the staging of all files in the staging area
Here's how to undo the staging of all the files in the staging area:
git reset
How to write text into a file via the terminal
echo textToWrite >> fileToWriteInto
>>
will append your text to the end of the file's content.>
will overwrite any existing content of the specified file.- Suppose you need to use symbols, like the exclamation mark (
!
), prepend each with a backslash (\
) mark. In doing so, Git will analyze the character as a text—not a command.
Here's an example:
Write, Hello!!!
into a file via the command line:
echo Hello\!\!\! >> fileToWriteInto
Dangerous Git Commands
Commands that permit you to undo changes are generally dangerous because they can permanently delete your work—if you do it wrongly!
Therefore, be super careful with these commands!
How to amend your last commit
Suppose you forgot to include something in your last commit—for instance, a file. In that case, do the following:
- Use the
git add <fileName>
to stage the missing content. - Run the following code.
git commit --amend
After you've invoked the snippet above, a COMMIT_EDITMSG
file will open, prompting you to update your previous commit message.
You can choose to update the previous commit message or retain it.
Once you've decided on the message to use, exit the COMMIT_EDITMSG
file so that Git can create the commit.
Afterward, Git will automatically replace your last commit with this updated version.
Use the --amend
command cautiously—as amending a commit changes the commit's SHA-1. --amend
replaces an old commit with a new one.
Therefore, to avoid confusing other collaborators, it's best not to amend any commit you have pushed (shared)!
In other words, amend only the commits that no one has pushed anywhere. Otherwise, you may end up destroying a commit on which other developers rely.
How to forcefully push to a remote repository
Suppose you wish to forcefully overwrite a remote repository with your local .git
repo. In such a case, use run:
git push --force
By so doing, Git won't ask you to update your local branch before pushing to the remote repo.
In other words, Git's default setting compels you to update your local branch with the latest commits of the remote repository to which you wish to push.
However, the --force
flag allows you to override Git's default configuration.
Keep in mind that git push --force
is a dangerous command because:
- It makes it easy to erase commits your collaborators recently pushed to the remote repo.
- The local repo you are moving upstream will replace any old commit on which your colleagues' new work still relies.
- Consider using
--force-with-lease
instead of the--force
flag.--force-with-lease
will alert you if someone has updated the remote repository since the time you last fetched. - Using git revert is a safer way to undo a commit you've pushed to a remote repository. It is a non-destructive command that does not rewrite commit histories.
How to rebase Git commits
Git rebasing is a technique used to change the base of a specific commit from one branch to another.
In other words, Git rebase allows you to cut off one branch's commit and reapply it to another branch.
The three main things people do with the git rebase
command are:
- Modify a previous commit message
- Merge multiple commits
- Delete redundant commits
Use the rebase
command cautiously—as amending a commit changes the commit's SHA-1. rebase
replaces an old commit with a new one.
Therefore, to avoid confusing other collaborators, it's best not to rebase any commit you have pushed (shared)!
In other words, rebase only the commits that no one has pushed anywhere. Otherwise, you may end up destroying a commit on which other developers rely.
Let's discuss some helpful ways to use the rebase
command.
How to modify a previous commit message
Suppose you wish to amend a previous commit message. In that case, use the rebase
command like so:
git rebase -i HEAD~2
The snippet above tells Git to begin an interactive rebasing session from the two previous commits.
- The
-i
flag used above is the shorthand notation for the--interactive
flag. You can use any one of the two flags to begin an interactive rebasing session. - The interactive tool allows you to stop after each commit in the series you've specified (the previous two in the case of our snippet above). At each stop, you can add files, change the commit's message, or do whatever else you wish to do.
HEAD~2
tells Git to rebase onto the parent of the last two commits. In other words, we instructed Git to rewrite commits as far back as the previous two.HEAD~2
is equivalent toHEAD~1^
. You can use any one of the two arguments to rebase onto the parent of the last two commits.
Once you've invoked the previous snippet, a git-rebase-todo
file will open in your text editor. The file will look similar to this:
pick 324c9db Create index.html file
pick 1d0923a Create Addition component
# Rebase 5b8c120..1d0923a onto 5b8c120
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup [-C | -c] <commit> = like "squash" but keep only the previous
# commit's log message, unless -C is used, in which case
# keep only this commit's message; -c is same as -C but
# opens the editor
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified); use -c <commit> to reword the commit message
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
- Interactive rebase lists commits from the oldest to the newest—rather than
git log
's way of listing from the most recent to the oldest. - To delete a commit, simply delete it from the list of commits in the
git-rebase-todo
file. - To reorder your commits, simply swap their positions in the
git-rebase-todo
file.
The opened file allows you to specify the commits where the script should stop so that you can edit the previous commit message.
For instance, suppose you only need to modify the 324c9db
commit's message. In that case, you would change 324c9db
's pick command to edit
like so:
edit 324c9db Create index.html file
pick 1d0923a Create Addition component
Then, you would save and close the git-rebase-todo
file.
Afterward, Git will go back to the 324c9db
commit and drop you a piece of information on the command line that looks like this:
$ git rebase -i HEAD~2
Stopped at 324c9db... Create index.html file
You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
In other words, run git commit --amend
to modify the 324c9db
commit's message. Then use git rebase --continue
to finish the rebase process.
How to squash commits
The interactive rebase tool lets you squash (merge) two or more commits together.
For instance, suppose you began an interactive rebasing session from your project's root commit like so:
git rebase -i --root
Let's now assume that after running the snippet above, a git-rebase-todo
file opened with four commit histories similar to this:
pick 7e8525d Create project directory
pick 5b8c120 Initialize NPM
pick 324c9db Create index.html file
pick 1d0923a Create Addition component
You can merge the two most recent commits with the third one by changing the word pick
to squash
like so:
pick 7e8525d Create project directory
pick 5b8c120 Initialize NPM
squash 324c9db Create index.html file
squash 1d0923a Create Addition component
Once you save and close the git-rebase-todo
file, a COMMIT_EDITMSG
file will open, prompting you to merge your previous commit messages.
In other words, your COMMIT_EDITMSG
file would look similar to this:
# This is a combination of 3 commits.
# The first commit's message is:
Initialize NPM
# This is the 2nd commit message:
Create index.html file
# This is the 3rd commit message:
Create Addition component
You need to merge the three commit messages.
Here's an example:
# This is a combination of 3 commits.
Create package.json, index.html, and Addition.js files
Afterward, save and close the COMMIT_EDITMSG
file so that Git can finish the squashing process.
How to split a previous commit
The interactive rebase tool allows you to split a previous commit into multiple commits.
For instance, suppose you began the interactive rebasing session from your project's root commit like so:
git rebase -i --root
Let's now assume that after running the snippet above, a git-rebase-todo
file opened with three commit histories similar to this:
pick 5b8c120 Initialize NPM
pick 324c9db Create index.html and style.css files
pick 1d0923a Create Addition component
You can split the middle commit (324c9db
) into two different commits.
In other words, you can split Create index.html and style.css files
into two commits: the first will use "Create index.html file" as its commit message, and the second will use "Create style.css file".
Here are the steps required to split your previous commit:
1. Change pick to edit
Change the pick
command to edit
for the commit you wish to split.
Here's an example:
pick 5b8c120 Initialize NPM
edit 324c9db Create index.html and style.css files
pick 1d0923a Create Addition component
Save, and close the git-rebase-todo
file once you've changed the command.
Afterward, Git will go back to the 324c9db
commit and drop you a piece of information on the command line that looks like this:
$ git rebase -i --root
Stopped at 324c9db... Create index.html and style.css files
You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
2. Reset the commit
At this stage, reset the commit to the one before the HEAD pointer like so:
git reset HEAD^
The snippet above will move the HEAD pointer to the commit located before the one you wish to split.
In other words, the git reset
command will update your project's staging area with the content of the commit right before the one you want to split.
Therefore, you can now create and commit new files individually.
- Suppose you do not want
git reset
to update your staging area. In that case, add a--soft
flag to the command—for instance,git reset --soft HEAD^
. By so doing, Git will only move the HEAD pointer to the previous commit while leaving the staging area untouched. - Suppose you want
git reset
to move the HEAD pointer, update your staging area, and update your working directory. In that case, add a--hard
flag to thereset
command—for instance,git reset --hard HEAD^
. - A hard reset operation is a destructive command that will overwrite your working directory's files. Therefore, use it cautiously.
3. Stage and commit files
Once you've reset your HEAD pointer, you can begin to stage and commit files.
For instance, you can split "Create index.html and style.css files" into two commits by staging and committing them like so:
git add index.html
git commit -m "Create index.html file"
git add style.css
git commit -m "Create style.css file"
4. Finish the rebase process
When you've finished splitting your previous commit, end the rebase process by running:
git rebase --continue
Git changes the SHA-1s of all the commits following a rebase change. Therefore, ensure you've not already pushed any of those commits to a shared repository.
How to replace a working directory's file with the last committed or staged version:
git checkout -- localFileToDeleteAndReplace
Alternatively, you can also use:
git restore localFileToDeleteAndReplace
The two commands above are dangerous commands that will permanently delete all the changes in the local version of the specified file.
In other words, Git will replace your local file with the last committed or staged version.
How to Share Git Repository
Sharing a Git repository online makes it easy for collaborators to collaborate on a project from anywhere, at any time.
Moreover, GitHub—a popular online platform used for sharing .git
repositories—takes Git collaboration to a whole new height.
To share your Git repository (that is, your project's committed file versions) on GitHub, follow this How to host a Git repository on GitHub guide.
Overview
This article discussed all you need to get started with Git.
Useful Resources
Below are links to other valuable content on how to use Git.
- About Version Control
- A collection of useful
.gitignore
templates - Git Cheat Sheet
- Undoing Things
- Reset Demystified
Get your free PDF Git cheat sheet.
Use it to easily remember the Git commands you need for your projects.