Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mercurial - View all changesets that modify specific line in file

Annotate gets you as far as seeing the most recent change to that line, if that change is a merge then I have no choice but to trawl through the revision history and find the next time it was modified.

I've also tried hg grep -l '[contents of line]' but:

  • a) I can't figure out how to target specific files (so it takes forever in a moderately sized repo)
  • b) It seems to only return the last revision number

The following link is vaguely similar - How to find all changsets where a reference to a function was modified?

like image 371
Simon Frost Avatar asked Mar 13 '13 22:03

Simon Frost


3 Answers

Use Tortoisehg:

  1. View -> Manifest
  2. Right click on file interested in and click "File History"
  3. click "annotate with revision numbers"

The top panel allows you to quickly see the history of the file in terms of commits, the bottom panel shows the annotated file based upon the selected version in the top panel.

like image 55
Tom Avatar answered Oct 14 '22 14:10

Tom


Using the response of arielf without an extra script:

UNIX:

  • command:

      hg log --template '{rev}\n' <FILE> | 
           xargs -I @ hg grep <PATTERN> -r @ <FILE>
    
  • you can use this to add an alias to your configuration file (.hgrc):

      [alias]
      _grep_line_in_history = ! $HG log --template '{rev}\n' $2 | 
           xargs -I @ hg grep '$1' -r @ $2
    

WINDOWS:

  • command:

      FOR /F "usebackq" %i IN (`hg log --template "{rev}\n" <FILE>`) DO
      @(echo %i & hg grep <PATTERN> -r %i <FILE>)
    
  • alias:

      [alias]
      _grep_line_in_history = ! FOR /F "usebackq" %i IN 
           (`%HG% log --template "{rev}\n" "$2"`) DO @(echo %i & %HG% grep "$1" -r %i "$2")
    
like image 41
Mayra Delgado Avatar answered Oct 14 '22 12:10

Mayra Delgado


I think this requires a bit of (two-step) programming.

The following shell script works pretty well for me. It prints both the revisions and the matching lines. If you only want the revisions list, you may add a step to strip the matching text and leave only the revision prefix, and possibly pipe through 'sort -u':

#!/bin/bash
#
# script to grep for a pattern in all revisions of a file
# Usage: scriptname 'pattern' filepath
#
function fatal() {
    echo "$@" 1>&2
    exit 1
}

function usage() {
    echo "$@" 1>&2
    fatal Usage: $0 pattern file
}

case "$1" in
    '') usage 'missing pattern to search for' ;;
    *)  Pat="$1" ;;
esac

if [ "$2" != '' ]; then
    File="$2"
else
    usage 'must pass file as 2nd argument'
fi

# -- generate list of revisions (change-sets) involving $File
for rev in `hg log --template '{rev}\n' $File`; do
    # -- grep the wanted pattern in that particular revision
    hg grep "$Pat" -r $rev $File
done

Notes:

  • not fully foolproof (e.g. quotes in the pattern)
  • I don't check for file existence to support renamed/removed files as well
like image 33
arielf Avatar answered Oct 14 '22 14:10

arielf