Suppose I have 2 tags X
and Y
such that
tag X log history: C1 C2 ... Cn
tag Y log history: Z1 Z2 ... Zm
If hash(Ci) = hash(Zj)
(for a given i
and j
) and I want to know all tags having commit Ci
I can just do, as answered in 'How to list all tags that contain a commit?',
git tag --contains Ci
and that would give me X
and Y
.
Is it possible to get the same response for the case that hash(Ci) != hash(Zj)
but they both apply the same changes (say, for instance, they both add the same line in the same file but they differ in the commit message)?
Edit
By saying that a tag "contains a given commit's changes" I mean that in the tag's log history, there's a commit C
applying the same modifications than the given commit.
The general I would think of would be :
The hardest part is to determine 1., so first the easiest part :
# in a file, or as the output of a commit :
eacf32c
44df701
...
just run repeatedly git tag --contains
, and merge the results together :
cat thelist.txt | while read sha; do git tag --contains $sha; done | sort -u
this depends a lot on how you intend to target said changes. Here are some examples :
if you know you only want to target commits applied using git cherry-pick
, chances are the commit messages will be a lot similar : git log --all --grep "one discriminating sentence"
or git log --all --grep "#issuenumber"
will probably give you a good starting point
if you want to target commits that added or removed one specific line : start from git log --all -S "a specific line"
, or git log --all -G "a specific line"
(read the doc for -S and -G if you need more explanations on how they work).
You can also spot a change in that/specific/file.txt
or that/specific/dir
by running :
git log -S "a specific line" -- that/specific/file.txt
git log -G "a specific line" -- that/specific/dir
git patch-id
git rebase
to spot commits that are already applied on target)Using it on the complete list of commits of your repo will be a bit involved, but it can be automated :
first compute the patch-id for the changes you want to spot :
$ git show A | git patch-id --stable
# this will give you a two fields output :
# a hash for the diff itself the hash of the commit
3bbe48e8ce5714b78900653e618ff4dc41205ffb 84d48dcd44d440d3a35177c92c897d2efae93346
then compute all patch ids, and grep for the one you want :
git rev-list --all | while read sha; do git show $sha | git patch-id; done
| grep "^3bbe48e8ce5714b78900653e618ff4dc41205ffb"
the second column will be the list of commits : ... | awk '{ print $2 }'
rather than listing all commits in your repo (git rev-list --all
), you may want to narrow the initial search with one of the first commands : feed in the list produced by git log --grep ...
or git log -S ...
or git log -- that/specific/dir
...
you can use the same trick for "the patch on a specific file" by changing the git show
commands :
git show $sha -- file1 file2 dir3 | git patch-id
you can write your own script, that takes in a commit id, and checks if it contains what you want
etc, etc, etc ...
Note : if you have a git log
command that allows you to spot some commits you are interested in, you can turn it in a command which only outputs the commit hashes, by removing all fomatting options (--onelin
, --graph
, --format
...) and replace them with --format="%H"