Internet Latest news security software Technology Reviews

Git Commit: A Master Class

Laptop on a blue background showing a Linux command prompt.
fatmawati achmad zaenuri/

The Git commit command stores copies of the changes from your working directory in your Git repository. But it can also be used to amend existing commits and to revert commits, too.

A basic requirement of any version control system is to store different versions of files for you. In Git, the command that does this is commit. Here’s everything you need to know.

What Is a Commit in Git?

Commits are the series of snapshots made throughout the lifecycle of a project that make up its development history. Commits are what allow us to extract a version of the project as it was at different points in the past. Why is that important?

Version control systems (VCSs) are most commonly used with software source code and development projects. But they can be used successfully with any collection of text files, such as Markdown files containing chapters of a book.

You might not want every file in your project directories to be handled by the VCS, so you need to be able to nominate the files you want to be version controlled. This adds them to the version control view of the project. They’ll be monitored for changes.

Another way to achieve this is to use an ignore list. This tells Git which files, directories, or types of files it should always ignore.

Over time, as new files are added to the project, some will require being added to the version control system. In Git, this is handled by the add command. Actually, the add command does double service, as we’ll see.

In order to maintain a history of the changes that have been made to the project, you’ll periodically ask Git to store a snapshot of the state of the project, using the commit command. This is where the add command reappears in our workflow. We use the add command to tell Git which changed files we want to have included in the snapshot. Then we use commit to tell Git to create the snapshot.

Configuring the commit Command

Information about the commit is stored with it, so that it’s always possible to know who made the commit, when, and what the commit contains. Some of this metadata is captured at commit-time, such as the commit message.

Metadata relating to the identity of the members of the development team can be configured by each user, to prevent repeatedly providing the same information.

To set your name globally for all repositories on your computer, use this command.

git config --global "Dave McKay"

Setting the global Git user name

To verify your name has been set, use this command.

git config --global

Checking the Git global user name

If you need to use a different name on a particular repository, change into the project’s directory and use the same command without the --global option.

git config "McKay, David"
git config

Setting a repository-specific Git user name

We’ve now got a different default user name for this repository, and our global name is still used for other repositories.

In a similar fashion, we can set an email address either globally or for a single repository by including or omitting the --global option.

git config "[email protected]"
git config --global "[email protected]"
git config
git config --global

Setting global and repository-specific Git default user email addresses

These settings are held in config files. Global Git settings are held in “~/.gitconfig”, and repository-specific settings are held in the repository’s “.git/config” file.

The commit command references and uses these values as it operates.

Using the commit Command

The basic use of the commit command is to take the files that are in the staging area, known as the index, and store them as a commit in the current branch of the repository.

A Basic Commit

We’ve got a project with a changed file. We’ll use the add command to stage the file, then commit it. We’re using the -m (commit message) option so that we can provide a short description of the purpose of the changes. If we don’t use this option, we’re prompted for a commit message as the commit takes place. It’s more convenient to add one on the command line.

git add jibber.c
git commit -m "Updated help text"

Staging and committing a single file

If we use the git log command we can review the details of the commits, in chronological order, with the most recent commit at the top of the list.

git log

Checking the Git repository log

The commits are displayed in less.

The latest commit at the top of the Git log

The commit has been tagged with the name and email address we provided earlier, and our commit message is recorded too.

Auto-Staging Files

Staging many files can take a little time. A different approach is to use the -A (all) option with add.

This automatically stages all modified files along with all currently untracked files. The staging of untracked files respects the settings in your “.gitignore” file. Git won’t stage files you’ve told it you don’t want to be included. Finally, files in the index that are no longer in the working directory are removed from the index.

Plainly, the -A option can cause a lot to happen all at once. The --dry-run option gives you a preview of the changes without actually performing them.

git add -A --dry-run

Using --dry-run to preview the files that will be staged and unstaged

In our example, it’ll stage two modified existing files, and two new files. Let’s go ahead and use the -A option before we use the commit command.

git add -A
git commit -m "Enhanced parsing"

Committing changed and newly created files, after using the add -A option

We can see that altogether four files are changed. Two of them are the newly created files, which are listed.

Staging and Committing at the Same Time

The commit command has a lowercase -a (all) option. This performs the staging and the committing of files in one step.

The commit -a option stages and commits modified existing files, and removes files from the index if they have been removed from your working directory. It doesn’t automatically stage untracked files.

Like the add command, the commit command has a --dry-run option that allows you to preview its actions before executing it.

git commit -a --dry-run

Using the commit -a option to preview changes without performing them

Now let’s carry out the command.

git commit -a --dry-run

Using the commit -a option to stage and commit in one step

The files are staged and committed for us.

Committing to a Different Branch

If you’ve made some changes to files in your work directory then realize you didn’t checkout the correct branch, you need to get your changes committed to the correct branch without affecting the current branch.

Git doesn’t have a command for committing to a different branch. But you can rectify this situation with a little bit of Git dexterity.

We’ll use the Git stash command to make a copy of the changes. Then we’ll check out the correct branch and apply the changes from the stash. To apply the stashed changes we’re using the pop command rather than the apply command. The pop command applies the changes and also removes them from the stash.

We’ve made some changes in our repository’s new-parser branch. They should have been made in the classic-parser branch.

git stash
git checkout classic-parser
git stash pop

Stashing changes, checking out a branch, and applying the changes from the stash

We can now perform a commit, and update this branch.

git commit -a -m "Added pre-parser functions"

Committing the changes that were retrieved from the stash

If we return to the new-parser branch we can see that it is up to date, meaning the changes have been removed from your working directory, and your repository and files are in sync.

git checkout new-parser
git status

Checking the state of a branch to make sure it is up to date

RELATED: How To Update and Maintain Separate Git Branches

Making Changes to Commits

If you need to improve your commit message—perhaps you’ve spotted a typo in it—or you forgot to stage a file that should have been included in the commit, you can use the --amend option to put things right. The caveat is, this shouldn’t be used on commits that have been pushed to a remote repository.

In our last commit message, “fraze” should have been “phrase.” If we use git log we can see this.

The Git log with a type highlighted

To correct this, we’ll use the --amend option like this.

git commit --amend -m "Optimized phrase identification"

Using the commit --amend option to correct a commit message

If we use git log once more, we can see the old commit has been replaced by a new one with the corrected commit message.

The Git log showing the corrected commit message

If we want to add a file that we forgot to stage, we can commit that file so that it appears as part of the previous commit.

We’ll use add to stage the file, then make a commit with the --amend option. The --no-edit option means we don’t need to provide a new commit message. The previous commit message is retained.

git add jibber.c
git commit --amend --no-edit

Committing a file to the previous commit

Removing Changes From a Commit

If you’ve inadvertently staged and committed a file that you didn’t intend to, you can remove that file from the commit using the reset command. We’ll reset the commit back to the staging area, or index. Then we’ll remove the file, and re-commit the rest of the files.

To reset the last commit to the staging area, we use the reset --soft command. HEAD~ is shorthand for “the commit behind the HEAD of the project commit timeline”, or in English, “the last commit.”

git reset --soft HEAD~

Sending the last commit back to the staging area

To remove the file that shouldn’t have been included, we use the reset --mixed command. This resets those changes back into the working directory, recreating the modified file as an unstaged, uncommitted file.

git reset --mixed jibber.c

Removing a file from the Git staging area

We need to commit the other files that are left in the index.

git commit -m "Experimental tweaks"

Committing the files that remain in the staging area

The other two files that were in the original commit are re-committed for us.

RELATED: How to Fix, Edit, or Undo Git Commits (Changing Git History)

Reverting an Entire Commit

Sometimes undoing an entire commit is the easiest thing to do. It puts your working directory and repository back to the state they were in before you committed.

We need to use the commit’s hashed reference ID. We can find this using git log:

The Git log with a commit identifier highlighted

Copy that reference and use it in the revert command:

git revert e5bd4560aef8164c6ca9d6d4620b9db7f66aecc8

Reverting a commit identified by its commit ID

This will open your default editor so you can edit a revert message. There is a default message entered for you. You can either use this, or edit it to your liking.

Editing the revert message, with the default message highlighted

When you’re happy with your revert message, save the file and exit the editor. In nano, you do this with “Ctrl+O”, and “Ctrl+X.”

The completed revert action, undoing an entire commit

Using git log once more, we can see that a new commit has been added that undoes the changes of the reverted commit.

The Git Swiss Army Knife

Obviously, commit is one of the most important Git commands. It can do a lot, so there’s a lot to learn. Getting to grips with its lesser-used features is time well spent. When you need to correct a mistake—right now—you’ll be glad you’ve prepared in advance.

RELATED: How to Use Git merge