Git Commit -a: Stage & Commit Files in a Single Step

Using git for versioning your projects? In this short tutorial, we uncover the time-saving benefit of using the -a option to stage and commit files in a single step! Be careful though -- it only works for tracked files!
git commit a command alpharithms

Git offers developers a range of features to provide powerful versioning for software projects. Git protocols come with many features and can often feel overwhelming. The -a` flag automatically stages files that have been modified or deleted to help improve workflow efficiency.

This option does not affect any files that Git is not aware of yet, however. In this short article, we’ll take a look at setting up a basic project with git-mediated versioning and demonstrate the impact of the -a option. Some familiarity with Git will be assumed but all steps will be outlined clearly.

Note: The -a option is used in this tutorial but can also be passed as -all while providing the same functionality.

Quick Intro: Setting up a Git Project

To demonstrate the use of the -a option in Git, we’ll set up a sample project, initialize Git, add our files, make some changes, add those again, and compare the differences. You will need to have Git installed to follow along. Our steps will be as follows:

  1. Create a sample project with a root directory, sub-directories, and sample files containing some amount of random data.
  2. Initialize Git in our sample project.
  3. Use the add, commit, and commit -a commands.

A sample project, complete with sample sub-directories containing sample files with sample content will be created using the create_sample_project.py script (available on Github) that reflects the following structure:

.
└── sample_project/
    ├── sample_dir_0/
    │   ├── sample_file_0_0.txt
    │   ├── sample_file_0_1.txt
    │   └── sample_file_0_2.txt
    └── sample_dir_1/
        ├── sample_file_1_0.txt
        ├── sample_file_1_1.txt
        └── sample_file_1_2.txt

Here we see a root directory, two sub-directories, and 3 files within each subdirectory. Each sample file contains a random string of ASCII characters so that Git can detect changes later. From sample_file_0_0.txt:

AFEcZwbWrMVtrwMQEDgebMIfIbZoFNGVUsVUrvASSWnYNrQZFcUBYFRlwgNZxTjZJCvzFUbKyaExqbKlbduAWnhsrGeGLaXhdZxEyPHeQHXSGIWdnfhBppvxGErlAxzzybwQSxTYdtwvAbnGyWwCRyBIeOqamwRbDpImFHaFnUerhsPOFysqwGoiBdphdcUqSojdBLMbWKbTiRqfcmvEiKxjyhXooUAylbGZpFMYWnLTVcPxIJiEKPYPzgMBOlqd

Nothing special here, just 256 random ASCII characters. Next, we’ll initialize Git in our directory by running the git init command as follows:

$ git init

// output
Initialized empty Git repository in /path/to/the/sample_project/.git/

The git status command will provide information related to the current state of version tracking in this sample project:

$ git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        sample_dir_0/
        sample_dir_1/

nothing added to commit but untracked files present (use "git add" to track)

The last line is very telling and hints that no files are currently being tracked. If the git commit command is run, a very similar message will be displayed. Taking the advice of Git’s messaging system, the git add sample_dir_0/* command will notify git about all files in sample_dir_0 and begin tracking those. Re-running the git status command now displays the following to the terminal:

$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   sample_dir_0/sample_file_0_0.txt
        new file:   sample_dir_0/sample_file_0_1.txt
        new file:   sample_dir_0/sample_file_0_2.txt

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

This indicates that all files in the sample_dir_0 directory are being tracked and that there are still un-trakced files in the sample_dir_1 directory.

Git commit -a

The -a option passed to the commit command is described in the official git documentation as follows:

Tell the command to automatically stage files that have been modified and deleted, but new files you have not told Git about are not affected.

“Staging” a file means preparing it for a commit command and resulting push if working with a remote repository. When the commit command is issued, Git will add changes to any files on the “stage” which have been added via the add command at some point. Currently, this includes all files in the sample_dir_0 directory.

Commit Files in sample_dir_0

The commit command requires that a message is provided indicating what changes were made. Using the -m flag will prevent the default text editor from opening (VIM in the case of most Unix-based systems.) This will add all changes from files currently added to the stage (files in sample_dir_0):

$ git commit
Aborting commit due to empty commit message.

$ git commit -m "initial commit" -v

// output, via the -v flag
[master (root-commit) d185b55] initial commit
 3 files changed, 3 insertions(+)
 create mode 100644 sample_dir_0/sample_file_0_0.txt
 create mode 100644 sample_dir_0/sample_file_0_1.txt
 create mode 100644 sample_dir_0/sample_file_0_2.txt

$ git status

// output
On branch master
Untracked files:
    (use "git add <file>..." to include in what will be committed)
        sample_dir_1/
nothing added to commit bu untraced files present (use "git add" to track)

Here the -v option (verbosity) outputs all files that have been updated in this commit. To followup, the git status command indicates that there are untracked files in the sample_dir_1 directory — because those files weren’t included in the the git add command earlier.

Commit Files in sample_dir_1

The simple version of using git commit -a is that it will “commit all changed files.” Unfortunately, Git does not automatically add previously untracked files via the -a option. It will only automatically add changes from currently tracked files and deleted files that were previously tracked. Running the git commit -a -m "second commit" && git status command will produce the following:

On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        sample_dir_1/

nothing added to commit but untracked files present (use "git add" to track)

In other words; files in sample_dir_1 were not staged or committed. However, if we open the file sample_dir_0/sample_file_0_0.txt and alter its content, the git status command will now produce the following output:

$ git status

// output
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   sample_dir_0/sample_file_0_0.txt

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

no changes added to commit (use "git add" and/or "git commit -a")

This message indicates that in order to stage the changes made in sample_file_0_0.txt one must do two things:

  1. Use the add command
  2. Use the commit command

Using the -a Flag Correctly

In other words, staging and committing files is a two-step process. However, the -a option allows this to happen in a single step as follows:

$ git commit -a -m "second commit" -v

// output
[master 92c024a] second commit
 1 file changed, 1 insertion(+), 1 deletion(-)

$ git status

// output
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        sample_dir_1/

nothing added to commit but untracked files present (use "git add" to track)

Note the git status command now reflects only the untracked files in the sample_dir_1 directory. Passing the -a flag into the git commit command automatically stages changes to tracked files or deletions of existing tracked files and commits them in a single step.

Final Thoughts

The git commit -a command is incredibly useful when working with multiple files. Rather than having to pass in a list of all files that should be staged, sometimes across multiple directories, one can simply add any tracked files.

Keep in mind the -a option doesn’t stage new files that aren’t currently being tracked. This is a source of confusion for many first-time git users and can result in untracked changes if not addressed. Using the git status command can provide helpful feedback to avoid such issues.

Check out our article on adding an existing project to an empty Github repo for more insights on how to better utilize Git version controlling for your projects! Also, check out our article on how to add a new directory/folder manually to a Github repo which is deceptively difficult.

Zαck West
Full-Stack Software Engineer with 10+ years of experience. Expertise in developing distributed systems, implementing object-oriented models with a focus on semantic clarity, driving development with TDD, enhancing interfaces through thoughtful visual design, and developing deep learning agents.