Git's Hidden Gems: How to Stage Selective Changes with --patch flag
Published: 2024-02-28 03:51:20

Git is a potent tool, and even working with it for a few years, I end up learning something new from time to time.

TLDR;

> Running git add with --patch or -p will make git split the file changes into several hunks, display each hunk, and ask you to do with that hunk, most of the time you will choose between y or n which means stage or not.

**The Problem**
You see yourself in a scenario where you have two or more changes in the same file, and for some reason, you believe it would be better to split those changes into different commits. I usually do that to organize the commits in a way that makes it easier for the reviewers to read the changes.

Let's check how to do it in a very simple example:

Here's part of a [package.json](https://github.com/home-assistant/frontend/blob/dev/package.json) we are going to use as an example: 
```JSON
{
  "description": "A frontend for Home Assistant",
  "repository": {
    "type": "git",
    "url": "https://github.com/home-assistant/frontend"
  },
  "name": "home-assistant-frontend",
  "version": "1.0.0",
  "scripts": {
    "build": "script/build_frontend",
      ... 
     "test": "instant-mocha --webpack-config ./test/webpack.config.js --require ./test/setup.cjs \"test/**/*.ts\"",
  },
  "author": "Paulus Schoutsen <Paulus@PaulusSchoutsen.nl> (http://paulusschoutsen.nl)",
  "license": "Apache-2.0",
  "type": "module",
  "dependencies": {
    "@babel/runtime": "7.23.9",
    ...
  },
  "devDependencies": {
    "@babel/core": "7.23.9",
    ...
  },
  "_comment": "Polymer 3.2 contained a bug, fixed in https://github.com/Polymer/polymer/pull/5569, add as patch",
  "resolutions": {
    "@polymer/polymer": "patch:@polymer/polymer@3.5.1#./.yarn/patches/@polymer/polymer/pr-5569.patch",
    "@material/mwc-button@^0.25.3": "^0.27.0",
    ...
  },
  "packageManager": "yarn@4.1.0"
}
```

Let's say you had to add a new dependency to help you build a new feature:
```JSON
"dependencies": {
    "@babel/runtime": "7.23.9",
    ...
    "@new/dependency": "1.0.2"
  },
```
While testing, you realized that there was a flag missing in the scripts, so you also added it:
```JSON
 "scripts": {
   ...
   "test": "instant-mocha --missing-flag --webpack-config ./test/webpack.config.js --require ./test/setup.cjs \"test/**/*.ts\"",
}
```

You have finished implementing the feature and are now ready to commit. Running `git add -p package.json` will display one of the changes and ask what you want to do with this change:


![git prompt for git add -p package.json](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hoqq7l21chfe2s58xvsr.png)

There are a few options ([y,n,q,a,d,j,J,g,/,e,?]) But usually, you will choose between y (yes) or (no)

After choosing what to do, it will display the next change and repeat the question: 
![git prompt after response](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s59vhlq90tlny48hvbmc.png)

In the example, we are saying to Git to stage the first change but skip the second one.

![git prompt to git status](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k3ucg0ck8j3scaqthsbo.png)
Now we can commit the first change then stage the next change and commit it as well. 
Each change with the message that fits it best.

Thank you for reading!