Sling Academy
Home/DevOps/Explaining the ‘git add -p’ command (with examples)

Explaining the ‘git add -p’ command (with examples)

Last updated: January 27, 2024

The ‘git add’ command is a vital part of any Git user’s workflow, allowing for staged changes to be included in the next commit. However, what can one do when they need more control over exactly which changes get staged? This is where the power of partial staging with ‘git add -p’ comes into play. This tutorial covers the basics and progresses to advanced usage, providing practical examples to illustrate how ‘git add -p’ can enhance your version control workflow.

Introduction to ‘git add -p’

Git is a distributed version control system designed to handle projects ranging from small to very large with speed and efficiency. One of its main features is the staging area, where you can prepare your changes before committing them. With the ‘git add’ command, you can add file changes to the staging area, but this command adds all changes in a file by default.

To add more precision to this process, Git supports the ‘-p’ (or ‘–patch’) option with the ‘git add’ command. Using ‘git add -p’, you can stage parts of a file—hunks of changes—rather than the whole file. This is especially useful when you’ve made multiple changes to a file but want to commit them separately to keep the project history clean and coherent.

Basic Usage of ‘git add -p’

To demonstrate the ‘git add -p’ command, consider a simple file named ‘example.txt’ with the following content:

Line 1
Line 2
Line 3

Let’s say you’ve made changes to ‘example.txt’, resulting in the following lines:

Line 1 - modified
Line 2 - unchanged
Line 3 - added new content

To start an interactive staging session, run the following command:

git add -p example.txt

Git will now display the first ‘hunk’ of changes and prompt you for an action:

diff --git a/example.txt b/example.txt
index 46d5f99..3ae4f6b 100644
--- a/example.txt
+++ b/example.txt
@@ -1,3 +1,3 @@
-Line 1
+Line 1 - modified
 Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]? 

Here, you can decide to stage (‘y’), skip (‘n’), quit (‘q’), and more. If you press ‘y’, Git will stage this change and proceed to the next hunk.

Explanation of Options

During ‘git add -p’, you’re presented with several options for handling each hunk. The most common are:

  • y – stage this hunk for the next commit
  • n – do not stage this hunk
  • q – quit; do not stage this hunk or any of the remaining hunks
  • a – stage this hunk and all later hunks in the file
  • d – do not stage this hunk or any of the later hunks in the file
  • e – manually edit the current hunk
  • ? – print help

Edit a Hunk Manually

Sometimes, the suggested hunk does not match exactly what you want to stage. In this case, you can edit the hunk manually by typing ‘e’. This will open the hunk in your text editor. Lines starting with a ‘+’, ‘-‘, or space character are additions, deletions, or unchanged. You can manually edit this by changing:

  • + to – to unstage an addition
  • to – to discard a deletion
  • to + – to split or reduce

Here’s an example where we choose to only stage part of the changes:

--- a/example.txt
+++ b/example.txt
@@ -1,3 +1,3 @@
-Line 1
+Line 1 - modified
 Stage this hunk [y,n,q,a,d,e,?]? e

After typing ‘e’, the editor might show something like:

-Line 1
+Line 1 - modified

To stage only the addition without the modification, you could change it to:

 Line 1
+Line 1 - modified

Advanced Options

For more nuanced control over staging, a few advanced options exist within ‘git add -p’, such as:

  • Splitting hunks: ‘git add -p’ may group changes closely together into a large hunk. If you only want to stage part of these changes, you can split the hunk into smaller, more manageable pieces.
  • Staging untracked files: You can initiate an interactive add session with untracked files by running ‘git add -N’ followed by ‘git add -p’.

Real-World Example

Here’s a detailed example to illustrate how git add -p (patch mode) can be used in a real-world scenario where you want to stage and commit different sections of changes in a file separately.

Let’s say you have a file named code.js, and you’ve made three distinct modifications in different sections of this file. Each modification relates to a different feature or bug fix. To commit these changes separately for better clarity and history management, you can use git add -p.

# Check the current status of the repository
git status

# Start interactive staging for a specific file
git add -p code.js

# Interactive mode begins
# For each hunk, choose 'y' to stage, 'n' to skip, 'q' to quit, '?' for help

# Commit the staged changes with a descriptive message for the first feature
git commit -m "Feature 1 related changes in code.js"

# Repeat the interactive staging for the same file
git add -p code.js

# Commit the staged changes for the second feature
git commit -m "Feature 2 related changes in code.js"

# Repeat for other features or fixes, as needed
# ...

# Final status check
git status

# Optionally, commit or stash any remaining changes
# git commit -m "Remaining changes in code.js"
# or
# git stash

Repeat the process as necessary for each distinct set of changes you want to commit separately.

Conclusion

Throughout this guide, we’ve explored how ‘git add -p’ offers precise control when staging changes. By understanding and leveraging the interactive options available with ‘git add -p’, you can create cleaner commits that are easier to review and maintain.

Next Article: How to tweak Git commit timestamps (author and committer dates)

Previous Article: Understanding the ‘git rev-parse –abbrev-ref HEAD’ command (with examples)

Series: Git & GitHub Tutorials

DevOps

You May Also Like

  • How to reset Ubuntu to factory settings (4 approaches)
  • Making GET requests with cURL: A practical guide (with examples)
  • Git: What is .DS_Store and should you ignore it?
  • NGINX underscores_in_headers: Explained with examples
  • How to use Jenkins CI with private GitHub repositories
  • Terraform: Understanding State and State Files (with Examples)
  • SHA1, SHA256, and SHA512 in Terraform: A Practical Guide
  • CSRF Protection in Jenkins: An In-depth Guide (with examples)
  • Terraform: How to Merge 2 Maps
  • Terraform: How to extract filename/extension from a path
  • JSON encoding/decoding in Terraform: Explained with examples
  • Sorting Lists in Terraform: A Practical Guide
  • Terraform: How to trigger a Lambda function on resource creation
  • How to use Terraform templates
  • Understanding terraform_remote_state data source: Explained with examples
  • Jenkins Authorization: A Practical Guide (with examples)
  • Solving Jenkins Pipeline NotSerializableException: groovy.json.internal.LazyMap
  • Understanding Artifacts in Jenkins: A Practical Guide (with examples)
  • Using Jenkins with AWS EC2 and S3: A Practical Guide