Git Add | Adding Changes to Git’s Staging Area
Table of Contents
- What Does git add Do?
- The Staging Area
- How Do I Use git add?
- How to Undo git add?
- Choosing What to Stage With git add -p
- git add Options
- Do I Have to git add Every Time?
- Next Steps
What Does git add Do?
Git is a feature rich version control system used by programmers for tracking changes made to code files. However, one unique feature of Git that sets it apart from other version control systems is the staging area. The staging area is a temporary holding location where Git stages your changes before actually committing them to the repository, and eventually pushing them to a central repository. All changes must be staged before they can be committed, and
git add is the tool we use to make staging happen.
The git add command can be used to stage one file, multiple files, or stage changes in an entire directory. Before digging into the details of git add, let's take a look at a basic example of staging some changes in a mock git repo. We'll use this working tree in examples throughout the article:
git-add-ex/ | file1.ext | file2.ext | |---dir1/ |-------dir1file1.ext
After initializing this repo with
git init, we can then stage our entire working tree and make our initial commit using the following commands:
git add . git commit -m 'Initial commit' [master (root-commit) 720edf7] Initial commit 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 dir1/dir1file1.ext create mode 100644 file1.ext create mode 100644 file2.ext
Notice the output - git add doesn't actually give us any output unless an error is thrown. The git commit command will output basic info about which files were committed from the staging area into the Git repo.
It's a wise choice to use git add and git commit often. We can break up a large collection of changes into multiple smaller stages and commits. It's good practice to stage and commit in small chunks as you code.
The Staging Area
As we've mentioned already, the staging area - also known as the staging index - is where Git puts our changes prior to committing them to the repo. But what's the point? Why doesn't Git allow us to simply commit all changes to our repo in one fell swoop?
There are many instances where the staging area comes in handy, and in some ways it may even be helpful to think of it as a rough draft for your commits. Here's a few examples of when and why the staging area can be helpful:
Sometimes, we lose track of progress in the midst of coding and end up with a large amount of code changes that need to be committed. To stage and commit everything at once is contrary to our goal of leaving an easy to read history of our project's evolution. The
git add -pallows us to interactively choose which chunks of code to stage for a commit, allowing us to break our commits up into more reasonable sizes. In this way we can commit the bits of changes within a file that we need, instead of all the changes in the file at once.
You may be in the process of making multiple changes to a repo, and receive an unrelated request to fix a small bug. A typical approach is to make a new branch for this fix. However, the staging area allows us to make this small change in our current branch, and only stage and commit the small fix while leaving our other changes untouched for a separate stage.
Prior to making commits to a repo, it's common to review the changes first. The staging area allows you to focus in on each individual change prior to making the decision to commit or not. You can run a diff command like
git diff --stagedto see the differences between your staged changes and the last commit, to see if it makes sense before you commit.
How Do I Use git add?
Using git add is straightforward in most cases. The basic syntax is as follows:
git add <path>: Use git add to stage a specific file or directory.
git add .: Stage all files and directories in the working tree unless specified otherwise in .gitignore
git add -p: Use an interactive mode to choose which hunks of changes to stage.
Using git add often comes after creating a new branch and checking it out, then making changes to one or more files. Let's give that a try with our previous example working tree:
$ git branch updatefile $ git checkout updatefile Switched to branch 'updatefile'
Now, let's write and save some text inside
file2.ext, and stage those changes. We can git add a folder or specific file by simply specifying the path after git add. We'll also use git status for a quick review of the staging area.
$ git add file2.ext $ git status On branch updatefile Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: file2.ext
A glance at the output tells us we have a change staged in our updatefile branch awaiting a commit or restore. But before we do any of that, let's make some changes to both
dir1/dir1file1.ext and stage those changes as well:
$ git add . $ git status On branch updatefile Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: dir1/dir1file1.ext modified: file1.ext modified: file2.ext
Here we used
git add . to stage our two changes at once, and as you can see from the output, all three of our changes are waiting patiently in the staging area of our
updatefile branch. Now, we could commit all these changes in one chunk, but what if we belatedly realized these changes should be in three separate commits?
No problem, we can undo these staged changes and then use our interactive mode to break up our changes into multiple stages and commits.
How to Undo git add?
As seen from the previous example output, git restore can be used to undo git add and restore files in the working tree from the staging area. The syntax is as follows:
git restore --staged <file>...
It's worth noting that git restore isn't the only command we can use to undo git add, and is in fact a relatively new addition to the git toolbox.
The git reset command has been around since Git's inception, and is the legacy option for undoing git add. However, git reset defaults to updating your branch and moving the tip. The git reset command is a more robust tool, but to simply undo a git add command without updating your branch, git restore is the way to go.
All that being said, let's get back to our example repo and undo those staged changes:
$ git reset Unstaged changes after reset: M dir1/dir1file1.ext M file1.ext M file2.ext
Now that we've resolved our problem of having staged our unwieldy chunk of changes, let's take a look at using the
git add -p command to interactively choose which changes to stage.
Choosing What to Stage With git add -p
-p option stands for
--patch. You can think of a patch as simply a set of changes in Git. You can use Git add patch to interactively add changes from one or more files into the staging area. The best part is that you can choose to include some, but not all the changes in a given file.
A "hunk" is a series of lines of code that are next to each other in a code file. These are also called contiguous lines of code.
The Git add patch command lets you pick the hunks that you want to include and exclude from the staging area. You can include hunks from one or more files in the staging area.
You can run
git add -p for Git to prompt you for each changed hunk in the working directory across all files that have changes. Or you can run
git add <filename> -p to have Git only prompt you to add hunks from a specific file.
For each hunk (set of changes) that Git identifies, it will prompt you with something like:
(1/1) Stage this hunk [y,n,q,a,d,e,?]?. You can type
y to add that hunk to the staging area or
n to disregard it. You can use
q to quit the interactive staging. There are several other hunk-handling options you can check out if desired.
Here is an example of running the interactive Git add patch command:
$ git add -p diff --git a/dir1/dir1file1.ext b/dir1/dir1file1.ext index e69de29..c8f7ee1 100644 --- a/dir1/dir1file1.ext +++ b/dir1/dir1file1.ext @@ -0,0 +1 @@ +Changed dir1file1 also! \ No newline at end of file (1/1) Stage this hunk [y,n,q,a,d,e,?]? y diff --git a/file1.ext b/file1.ext index e69de29..cc5a71d 100644 --- a/file1.ext +++ b/file1.ext @@ -0,0 +1 @@ +Changed file1! \ No newline at end of file (1/1) Stage this hunk [y,n,q,a,d,e,?]? n diff --git a/file2.ext b/file2.ext index fb94200..11476f3 100644 --- a/file2.ext +++ b/file2.ext @@ -1 +1,3 @@ -Made a change \ No newline at end of file +Made a change + +// Added important comment. \ No newline at end of file (1/1) Stage this hunk [y,n,q,a,d,e,?]? n $ git commit -m 'Commit a smaller hunk!' [updatefile2 0183d87] Commit a smaller hunk! 1 file changed, 1 insertion(+)
Note that for each hunk that Git identified above, it prompted us as to whether we wanted to add it to the staging area.
In this example output, git add -p has allowed us to stage and commit only one out of the three changes we made in our branch, a very helpful feature to say the least.
git add Options
The git add command comes with a quite a few options. Let's take a look at some that you're likely to come across:
git add *: This options tells git to stage all files in the current directory that don't begin with a dot. And to stage all files in subdirectories whether they begin with a dot or not.
git add -A: Will stage all files, including new, modified, and deleted files, as well as files in the current directory and sub-directories that belong to the same git repo.
git add -u: Will only stage modified tracked files, but not untracked files.
For a comprehensive look at all git add options, head over the the git add docs and take a look.
Do I Have to git add Every Time?
Technically, no. There is a Git shortcut that you can use to add and commit with a single command. You can use the git commit command with the
-a flag like:
git commit -a -m <commit-message>
-a flag tells Git to automatically stage all tracked file changes (including modifications and deletions but not untracked files), and commit them in one fell swoop.
This is a handy shortcut that can save you some time when you have a few small changes to stage and commit. However, for larger more complex commits, you should probably use git add every time.
The git add command is used for staging changes in Git prior to committing them to the current branch. It is helpful for reviewing changes prior to commits, breaking up changes into multiple smaller commits, or even making small changes unrelated to the current branch.
The result of git add isn't permanent, and can be reversed using git restore or git reset, which will keep any of the staged changes from reflecting in the commit history. For this reason, the staging area can be thought of as a rough draft for your commits.
Overall, git add and the staging area are an excellent feature that sets Git apart from other version control systems. To use it wisely, use it often.
If you're interested in learning more about how Git works under the hood, check out our Baby Git Guidebook for Developers, which dives into Git's code in an accessible way. We wrote it for curious developers to learn how Git works at the code level. To do this we documented the first version of Git's code and discuss it in detail.
We hope you enjoyed this post! Feel free to shoot me an email at firstname.lastname@example.org with any questions or comments.
Recommended product: Git Guidebook for Developers