Mercurial - View all changesets that modify specific line in file
Asked Answered
B

3

7

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?

Beatrice answered 13/3, 2013 at 22:4 Comment(0)
D
10

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.

Disproportion answered 14/3, 2013 at 2:5 Comment(2)
Maybe it's because I'm on a later version of TortoiseHg (3.2.3), but I don't see how this helps isolate a single line's changes? (I can't find the manifest option any more, but annotate files behavior from the explorer/plugin context menu seems to do what this answer suggests, which is just how a file looks at various revisions; you still have to find the line in question in each revision.)Ardeha
for missing manifest - #23458246Disproportion
C
3

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")
    
Catechize answered 21/12, 2015 at 12:59 Comment(0)
C
1

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
Cermet answered 13/3, 2013 at 22:42 Comment(1)
Wish there was a way to do this in an easier way. I dont use TortoiseHgSauerkraut

© 2022 - 2024 — McMap. All rights reserved.