Posted about 1 month ago. Visible to the public.

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.

Example

Consider the following git diff output.

Copy
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.

Using grepdiff

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 git diff.

First, grep your diff and play around with the regular expression until the output is what you want it to be.

Copy
git diff -U0 | grepdiff -E '# .+' --output-matching=hunk

Then, pipe it into git apply to stage.

Copy
git diff -U0 | grepdiff -E '# .+' --output-matching=hunk | git apply --cached --unidiff-zero

You can then commit your staged changes.

Copy
git commit -m "Remove useless comments"

Note the following.

  • git diff -U0 omits unchanged lines. You almost always want to grep only changed lines. git apply accepts this style when using the --unidiff-zero option.
  • The -E switch on grepdiff enables 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 + as \+), omit that switch.
  • Just to clarify, here is the remaining diff after applying the above:
Copy
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

Does your version of Ruby on Rails still receive security updates?
Rails LTS provides security patches for old versions of Ruby on Rails (3.2 and 2.3).

Owner of this card:

Avatar
Arne Hartherz
Last edit:
about 1 month ago
by Arne Hartherz
Keywords:
regex, regexp
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Arne Hartherz to makandra dev
This website uses cookies to improve usability and analyze traffic.
Accept or learn more