Tag specific Git commits based on commit message contents I am using GNU Bash 4.3, and Git 2.1.4, to tag certain git commits based on their commit messages. Specifically, I want to tag:


as v0.0.1 the commit with message "Commit 5",
as v0.0.2 the commit with message "Commit 10",


given the following commit log:

$ git log --format=oneline --decorate
924d9120dec9f61d0f99a5155c51bad63d24b37f (HEAD, master) Commit 10
c62b2f68ea6b8ff047dd5f1e99010ebf434709ef Commit 9
feec2d76977521018ff33fd6e109530fdb69291d Commit 8
9a25b2ea11d0aa19af33761c7c81bd10d0f17949 Commit 7
c7b02e556738e7cd2a2459e07af731e5677ab090 Commit 6
1bf5b98cf90340e714bd0bd13c7721f94749fa5f Commit 5
8a9c25eda46b3424a870584e4a8a4f90f6e5aa2c Commit 4
0ecf2464ec82a3aa74abb6f6c2127315ef4c2495 Commit 3
e18bdb2ae52f2149421965ff69d96dba46cd7c0a Commit 2
cf10d47067bef60ae787e5421e32b4541bdf52be Commit 1


Here is my initial solution:

$ v=(1 2); c=(5 10); for i in 0 1; do git tag -a v0.0.${v[$i]} -m "Tag v0.0.${v[$i]}" $(git rev-parse :/'Commit '${c[$i]}); done


This clearly works as desired:

$ git log --format=oneline --decorate
924d9120dec9f61d0f99a5155c51bad63d24b37f (HEAD, tag: v0.0.2, master) Commit 10
c62b2f68ea6b8ff047dd5f1e99010ebf434709ef Commit 9
feec2d76977521018ff33fd6e109530fdb69291d Commit 8
9a25b2ea11d0aa19af33761c7c81bd10d0f17949 Commit 7
c7b02e556738e7cd2a2459e07af731e5677ab090 Commit 6
1bf5b98cf90340e714bd0bd13c7721f94749fa5f (tag: v0.0.1) Commit 5
8a9c25eda46b3424a870584e4a8a4f90f6e5aa2c Commit 4
0ecf2464ec82a3aa74abb6f6c2127315ef4c2495 Commit 3
e18bdb2ae52f2149421965ff69d96dba46cd7c0a Commit 2
cf10d47067bef60ae787e5421e32b4541bdf52be Commit 1


But it seems excessively verbose and fragile.

Questions:


Instead of separately defining three arrays (v=(1 2); c=(5 10); for i in 0 1), can I create a single array for the two independent variables (e.g. in pseudocode: vc=((1 5) (2 10))) and then determine the incrementor's value automatically upon each iteration?
Instead of using a for loop, can I use brace expansion or some other more concise and elegant approach?


I would prefer a one-liner, but I do not require a one-liner.
If I had to write a "single-use" quickie command, I would write it like this:

while read version commit; do
    git tag -a v0.0.$version -m "Tag v0.0.$version" $(git rev-parse :/'Commit '$commit)
done


Then, as the script awaits input, type:

1 5
2 10
^D


In contrast to your parallel arrays, the main advantage of this approach is that each line constitutes a commit-version pair.