Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I find removed lines with git?

From time to time it happens that I want to re-add some code which I removed from a repository some time ago. I always use tools like tig to browse the history to find the commit which removed some lines.

Is there a way to find removed lines with git? Something like git-grep but for commit content instead of commit messages?

like image 588
musicmatze Avatar asked Apr 09 '16 11:04

musicmatze


People also ask

Does git blame show lines that were deleted or replaced?

git blame can tell you who last changed a file line by line. But how can you find out who deleted a line? You can pseudo-git-blame a deleted line using either of the following, depending on whether you want to do a simple string matching search or use a regex: git log -S [string] ./file.

What is git Oneline?

Git Log Oneline The oneline option is used to display the output as one commit per line. It also shows the output in brief like the first seven characters of the commit SHA and the commit message. It will be used as follows: $ git log --oneline.

What is git blame used for?

Summary. The git blame command is used to examine the contents of a file line by line and see when each line was last modified and who the author of the modifications was. The output format of git blame can be altered with various command line options.


1 Answers

If you remember some keyword, e.g., the name of a variable or function, in the removed lines, use pickaxe search as in

git log -Skeyword

or to see the deltas along with the commit messages

git log -p -Skeyword

Although -S searches for exact string matches a la fgrep, you can search for regex matches with -G instead.

Note that the argument to -S or -G is “cuddled” with no space in between.

Documentation:

-S<string>

Look for differences that change the number of occurrences of the specified string (i.e. addition/deletion) in a file. Intended for the scripter’s use.

It is useful when you’re looking for an exact block of code (like a struct), and want to know the history of that block since it first came into being: use the feature iteratively to feed the interesting block in the preimage back into -S, and keep going until you get the very first version of the block.

-G<regex>

Look for differences whose patch text contains added/removed lines that match .

To illustrate the difference between -S<regex> --pickaxe-regex and -G<regex>, consider a commit with the following diff in the same file:

+    return !regexec(regexp, two->ptr, 1, &regmatch, 0);
...
-    hit = !regexec(regexp, mf2.ptr, 1, &regmatch, 0);

While git log -G"regexec\(regexp" will show this commit, git log -S"regexec\(regexp" --pickaxe-regex will not (because the number of occurrences of that string did not change).

See the pickaxe entry in gitdiffcore [reproduced below] for more information.


diffcore-pickaxe: For Detecting Addition/Deletion of Specified String

This transformation limits the set of filepairs to those that change specified strings between the preimage and the postimage in a certain way. -S<block of text> and -G<regular expression> options are used to specify different ways these strings are sought.

-S<block of text> detects filepairs whose preimage and postimage have different number of occurrences of the specified block of text. By definition, it will not detect in-file moves. Also, when a changeset moves a file wholesale without affecting the interesting string, diffcore-rename kicks in as usual, and -S omits the filepair (since the number of occurrences of that string didn’t change in that rename-detected filepair). When used with --pickaxe-regex, treat the block of text as an extended POSIX regular expression to match, instead of a literal string.

-G<regular expression> (mnemonic: grep) detects filepairs whose textual diff has an added or a deleted line that matches the given regular expression. This means that it will detect in-file (or what rename-detection considers the same file) moves, which is noise. The implementation runs diff twice and greps, and this can be quite expensive.

When -S or -G is used without --pickaxe-all, only filepairs that match their respective criterion are kept in the output. When --pickaxe-all is used, if even one filepair matches their respective criterion in a changeset, the entire changeset is kept. This behavior is designed to make reviewing changes in the context of the whole changeset easier.

like image 138
Greg Bacon Avatar answered Sep 26 '22 19:09

Greg Bacon