Step-by-Step with Git: Advanced Commit Strategies

Let’s use a practical example to guide us through this process. By the end of this tutorial, you'll understand how to commit changes selectively, review modifications, and manage staged and unstaged changes.

Step-by-Step with Git: Advanced Commit Strategies
Photo by Farhat Altaf / Unsplash

In this post, we’ll dive deep into advanced committing in Git. We'll explore how to create and merge local commits effectively while maintaining clarity and organization in your codebase. Let’s use a practical example to guide us through this process. By the end of this tutorial, you'll understand how to commit changes selectively, review modifications, and manage staged and unstaged changes.

This post takes a more hands-on approach to mastering advanced Git commits. Rather than diving into theory, we'll explore practical examples to show how to create, manage, and refine local commits effectively in real-world scenarios. Let's get our hands dirty with Git!

1. Setting Up the Playground

We begin by setting up a sample Git repository to demonstrate advanced committing techniques.

1.1 Reviewing the Project Directory

Let’s first list the contents of our project folder:

$ ls -la 
total 9 
drwxr-xr-x 1 CZC1PR 1049089  0 Nov 30 09:18 ./ 
drwxr-xr-x 1 CZC1PR 1049089  0 Nov  9 09:27 ../ 
drwxr-xr-x 1 CZC1PR 1049089  0 Dec  1 08:46 .git/ 
drwxr-xr-x 1 CZC1PR 1049089  0 Nov 30 09:18 devops/ 
-rw-r--r-- 1 CZC1PR 1049089 32 Nov 30 09:12 README.md

The repository contains:

  • A README.md file.
  • A devops/ folder for Jenkins job examples.

1.2 Creating a Temporary Folder

For this session, let’s create a new tmp/ folder and add two files:

$ mkdir tmp
$ touch tmp/file01 tmp/file02

Verify the contents:

$ ls -la tmp/ 
total 0 
drwxr-xr-x 1 CZC1PR 1049089 0 Dec 12 08:35 ./ 
drwxr-xr-x 1 CZC1PR 1049089 0 Dec 12 08:34 ../ 
-rw-r--r-- 1 CZC1PR 1049089 0 Dec 12 08:35 file01 
-rw-r--r-- 1 CZC1PR 1049089 0 Dec 12 08:35 file02

2. Adding Content to Files

Add content to these files using the echo command:

$ echo "This is new file #1" > tmp/file01
$ echo "This is new file #2" > tmp/file02

Check the contents of the files:

$ cat tmp/file01
This is new file #1

$ cat tmp/file02
This is new file #2

3. Staging Changes

3.1 Initial git status

Run git status to see the current state of the repository:

$ git status
On branch main 
Your branch is up to date with 'origin/main'. 
Untracked files: 
  (use "git add <file>..." to include in what will be committed) 
        tmp/

3.2 Adding the tmp/ Folder to Staging

Add the folder to the Git repository:

$ git add tmp/

Now, check the status again:

$ git status 
On branch main 
Your branch is up to date with 'origin/main'. 
Changes to be committed: 
  (use "git restore --staged <file>..." to unstage) 
        new file:   tmp/file01 
        new file:   tmp/file02

3.3 Committing the Staged Changes

Commit the changes with a meaningful message:

$ git commit -m "Added tmp folder with initial files"
[main 891defa] Added tmp folder with initial files 
 2 files changed, 2 insertions(+)
 create mode 100644 tmp/file01
 create mode 100644 tmp/file02

4. Making and Staging Changes Selectively

4.1 Modifying file01

Add a new line to file01:

$ echo "This is new line for file #1" >> tmp/file01

Verify the content:

$ cat tmp/file01
This is new file #1
This is new line for file #1

Check the status:

$ git status 
On branch main 
Your branch is ahead of 'origin/main' by 1 commit. 
Changes not staged for commit: 
  (use "git add <file>..." to update what will be committed) 
        modified:   tmp/file01

4.2 Using git diff

View the differences:

$ git diff
diff --git a/tmp/file01 b/tmp/file01 
index 350b4fc..6335f6d 100644 
--- a/tmp/file01 
+++ b/tmp/file01 
@@ -1 +1,2 @@ 
 This is new file #1 
+This is new line for file #1

5. Selective Commit with git add --patch

Now let’s modify file02 to demonstrate selective staging:

$ echo "This is new line for file #2" >> tmp/file02

Run git diff again:

$ git diff
diff --git a/tmp/file01 b/tmp/file01 
@@ -1 +1,2 @@ 
 This is new file #1 
+This is new line for file #1
diff --git a/tmp/file02 b/tmp/file02 
@@ -1 +1,2 @@ 
 This is new file #2 
+This is new line for file #2

5.1 Interactive Staging with --patch

Use the --patch option to stage changes interactively:

$ git add --patch
diff --git a/tmp/file01 b/tmp/file01
@@ -1 +1,2 @@
 This is new file #1
+This is new line for file #1
(1/1) Stage this hunk [y,n,q,a,d,e,?]? y

diff --git a/tmp/file02 b/tmp/file02
@@ -1 +1,2 @@
 This is new file #2
+This is new line for file #2
(1/1) Stage this hunk [y,n,q,a,d,e,?]? n

5.2 Checking Staged and Unstaged Changes

Check the status:

$ git status
Changes to be committed:
        modified:   tmp/file01

Changes not staged for commit:
        modified:   tmp/file02

5.3 Committing Changes

Commit the staged changes:

$ git commit -m "Updated file01 with additional line"

6. Best Practices for Advanced Committing

  • Use git add --patch to stage changes selectively.
  • Keep commits small and focused on a single purpose.
  • Write descriptive commit messages to improve project traceability.
  • Use git diff and git diff --staged to review changes before committing.

Conclusion

Selective staging and advanced committing in Git are invaluable tools for managing complex projects. By breaking changes into logical commits, you make your history cleaner, debugging easier, and collaboration smoother. With practice, you’ll master these techniques, elevating your Git workflow to the next level.

Read next

Using Git Stash in Multi-Branch Workflows

You're likely to work with multiple branches for different features, bug fixes, and releases. While managing these branches, you might run into situations where you need to temporarily save your work without committing it, and later apply it on the same or even a different branch.

Applying and Clearing Git Stashes

In the previous post, we discussed how to use git stash to temporarily save changes without committing them. Now, we'll dive deeper into how to apply and clear stashes when you're ready to bring your changes back or clean up your stash history.

Git Stash: Temporarily Saving Changes

When you need to quickly switch branches, but you have uncommitted changes in your working directory. Committing these unfinished changes might not be desirable, and discarding them would result in a loss of your work. This is where Git’s stash command comes into play.