Git: How to add changes matching a regular expression
When you have many changes, and you want to spread them across different commits, here is a way to stage all changes matching a given regular expression for a single commit.
Consider the following
git diff output.
diff --git a/file1.rb b/file1.rb index 806ca88..36d536b 100644 --- a/file1.rb +++ b/file1.rb @@ -1,7 +1,5 @@ -# Here is a useless comment. -# It will be removed. class File1 - def foo + def bar # ... end end diff --git a/file2.rb b/file2.rb index 550e1c6..600f4e3 100644 --- a/file2.rb +++ b/file2.rb @@ -1,6 +1,5 @@ -# Here is another useless comment. class File2 - def foo + def bar # ... end end
While you can easily stage such changes using
git add -p, you can be much faster when there are many files with changes following the same pattern.
You need the
grepdiff tool. On Ubuntu systems, this is usually preinstalled from the
patchutils package. If not,
sudo apt install patchutils. You can then use it to grep through the output of
First, grep your diff and play around with the regular expression until the output is what you want it to be.
git diff -U0 | grepdiff -E '# .+' --output-matching=hunk
Then, pipe it into
git apply to stage.
git diff -U0 | grepdiff -E '# .+' --output-matching=hunk | git apply --cached --unidiff-zero
You can then commit your staged changes.
git commit -m "Remove useless comments"
Note the following.
git diff -U0omits unchanged lines. You almost always want to grep only changed lines.
git applyaccepts this style when using the
grepdiffenables the POSIX Extended Regular Expression syntax that you are used from Ruby. If you prefer basic syntax (i.e. where you escape control characters like
\+), omit that switch.
- Just to clarify, here is the remaining diff after applying the above:
diff --git a/file1.rb b/file1.rb index 49283bf..36d536b 100644 --- a/file1.rb +++ b/file1.rb @@ -1,5 +1,5 @@ class File1 - def foo + def bar # ... end end diff --git a/file2.rb b/file2.rb index 93e1660..600f4e3 100644 --- a/file2.rb +++ b/file2.rb @@ -1,5 +1,5 @@ class File2 - def foo + def bar # ... end end