]>
Commit | Line | Data |
---|---|---|
b0bf8f24 JH |
1 | CVS annotate. |
2 | ||
3 | The core GIT itself does not have a "cvs annotate" equivalent. | |
4 | It has something that you may want to use when you would use | |
5 | "cvs annotate". | |
6 | ||
7 | Let's step back a bit and think about the reason why you would | |
8 | want to do "cvs annotate a-file.c" to begin with. | |
9 | ||
10 | You would use "cvs annotate" on a file when you have trouble | |
11 | with a function (or even a single "if" statement in a function) | |
12 | that happens to be defined in the file, which does not do what | |
13 | you want it to do. And you would want to find out why it was | |
14 | written that way, because you are about to modify it to suit | |
15 | your needs, and at the same time you do not want to break its | |
16 | current callers. For that, you are trying to find out why the | |
17 | original author did things that way in the original context. | |
18 | ||
19 | Many times, it may be enough to see the commit log messages of | |
20 | commits that touch the file in question, possibly along with the | |
21 | patches themselves, like this: | |
22 | ||
23 | $ git-whatchanged -p a-file.c | |
24 | ||
25 | This will show log messages and patches for each commit that | |
26 | touches a-file. | |
27 | ||
28 | This, however, may not be very useful when this file has many | |
29 | modifications that are not related to the piece of code you are | |
30 | interested in. You would see many log messages and patches that | |
31 | do not have anything to do with the piece of code you are | |
32 | interested in. As an example, assuming that you have this piece | |
33 | code that you are interested in in the HEAD version: | |
34 | ||
35 | if (frotz) { | |
36 | nitfol(); | |
37 | } | |
38 | ||
39 | you would use git-rev-list and git-diff-tree like this: | |
40 | ||
41 | $ git-rev-list HEAD | | |
42 | git-diff-tree --stdin -v -p -S'if (frotz) { | |
43 | nitfol(); | |
44 | }' | |
45 | ||
46 | We have already talked about the "--stdin" form of git-diff-tree | |
47 | command that reads the list of commits and compares each commit | |
48 | with its parents. The git-whatchanged command internally runs | |
49 | the equivalent of the above command, and can be used like this: | |
50 | ||
51 | $ git-whatchanged -p -S'if (frotz) { | |
52 | nitfol(); | |
53 | }' | |
54 | ||
55 | When the -S option is used, git-diff-tree command outputs | |
56 | differences between two commits only if one tree has the | |
57 | specified string in a file and the corresponding file in the | |
58 | other tree does not. The above example looks for a commit that | |
59 | has the "if" statement in it in a file, but its parent commit | |
60 | does not have it in the same shape in the corresponding file (or | |
61 | the other way around, where the parent has it and the commit | |
62 | does not), and the differences between them are shown, along | |
63 | with the commit message (thanks to the -v flag). It does not | |
64 | show anything for commits that do not touch this "if" statement. | |
65 | ||
66 | Also, in the original context, the same statement might have | |
67 | appeared at first in a different file and later the file was | |
68 | renamed to "a-file.c". CVS annotate would not help you to go | |
69 | back across such a rename, but GIT would still help you in such | |
70 | a situation. For that, you can give the -C flag to | |
71 | git-diff-tree, like this: | |
72 | ||
73 | $ git-whatchanged -p -C -S'if (frotz) { | |
74 | nitfol(); | |
75 | }' | |
76 | ||
77 | When the -C flag is used, file renames and copies are followed. | |
78 | So if the "if" statement in question happens to be in "a-file.c" | |
79 | in the current HEAD commit, even if the file was originally | |
80 | called "o-file.c" and then renamed in an earlier commit, or if | |
81 | the file was created by copying an existing "o-file.c" in an | |
82 | earlier commit, you will not lose track. If the "if" statement | |
83 | did not change across such rename or copy, then the commit that | |
84 | does rename or copy would not show in the output, and if the | |
85 | "if" statement was modified while the file was still called | |
86 | "o-file.c", it would find the commit that changed the statement | |
87 | when it was in "o-file.c". | |
88 | ||
89 | [ BTW, the current versions of "git-diff-tree -C" is not eager | |
90 | enough to find copies, and it will miss the fact that a-file.c | |
91 | was created by copying o-file.c unless o-file.c was somehow | |
92 | changed in the same commit.] | |
93 | ||
94 | You can use the --pickaxe-all flag in addition to the -S flag. | |
95 | This causes the differences from all the files contained in | |
96 | those two commits, not just the differences between the files | |
97 | that contain this changed "if" statement: | |
98 | ||
99 | $ git-whatchanged -p -C -S'if (frotz) { | |
100 | nitfol(); | |
101 | }' --pickaxe-all | |
102 | ||
103 | [ Side note. This option is called "--pickaxe-all" because -S | |
104 | option is internally called "pickaxe", a tool for software | |
105 | archaeologists.] |