How to check that git commits contain string pattern in message?
In a pre-receive or update hook, you are given—on stdin, or as arguments—a reference name, the old value of the reference, and the new value of the reference. The update hook gets one reference, as arguments. You can make a single decision about the single reference update based on those three arguments: to allow it, or to prevent it. The pre-receive hook gets all the proposed updates, one per line, on its standard input, and you must read all of standard input before making your one decision: to allow all of the proposed updates to pass through to the next step—which includes running the update hook, one name at a time—or to deny the update as a whole.
In all cases, each reference uses its full, spelled-out format. Be sure to use all of it, so that you do not mistake tag X
, refs/tags/X
, for the different reference refs/heads/X
that names branch X
. Similarly, do not confuse branch name refs/heads/experiment/master
with refs/heads/master
, which would happen if you simply stripped off everything up through (i.e., including) the final /
. You may even get a request to update a reference that is neither a branch name nor a tag name, such as a refs/replace/
name-space item, or refs/notes/commits
.
Similarly, the old value and new value are two complete Git hash IDs, except that exactly one—never both—may be the special all-zeros "null hash". A null hash indicates that the reference is either being created (old value null, new value non-null) or destroyed (old value non-null, new value null).
Looking at commits
If you wish to look at all the incoming commits' messages, you must iterate over each commit in $oldhash..$newhash
, except that you must handle "reference being created" or "reference being destroyed" differently. When a reference is being created, it's sometimes impossible to know which commit(s), if any are coming in because of that new reference. Consider for instance the case where your pre-receive hook gets:
012...789 aaa...aaa refs/heads/br1
345...eee 321...def refs/heads/br2
000...000 999...999 refs/tags/v2.1
Now, refs/tags/v2.1
is being created (its old value is all-zeros). Its new value is 999...
, which is presumably either an annotated tag object or a commit object. But what if 999...
reaches a commit whose parent is 888...
and 888...
was not in the repository before? Then the newly created tag is perhaps the source of commit 888...
. On the other hand, the two branch names br1
and br2
are being changed as well. What if one of them reaches 888...
as well? (E.g., perhaps that's the grandparent commit of aaa...
.)
The nearest you can get to "commits introduced by new reference" is to use git rev-list <hash> --not --all
to get a list of commits reachable by the hash ID, that are not already reachable from all existing references. That would count new commit 888...
as reachable from the tag, even if it's also going to be reachable from br1
(provided you allow the update to br1
of course).
For your case, this may be fine: if you reject the commit for having a bad message on br1
, you can also reject the commit for having a bad message on v1.2
, meaning you reject the commit twice, but so what? Or it may not be fine, in which case, you must decide how you wish to handle it. Just remember that your options are to read all updates in a pre-receive hook, and allow them all to proceed or reject them all; or to check each update one at a time in an update hook, and allow that one update to proceed, or to reject it. In the pre-receive hook, since you have a global view of all updates, you can write fancy logic. In an update hook, you have a narrow view, and you cannot write fancy logic: you must keep it simple. Each has its advantages and disadvantages.
In any case, once you have an update, you can tell which commits will be reachable after the update that are not yet reachable:
git rev-list $newvalue ^$oldvalue | ...
and you can tell which commits were reachable from the old reference value that will no longer be reachable:
git rev-list $oldvalue ^$newvalue | ...
(the latter are commits that are being removed via force-push). In the ...
section of the code, you can read each commit hash and do whatever you like with it, such as:
... | while read hash; do
if git log --format=%B $hash | grep "$expr" >/dev/null; then
# grep found a pattern in the body printed by %B
else
# grep did not find the pattern
fi
done
Can clang-format tell me if formatting changes are necessary?
Starting with clang-format-10, you can use the --dry-run
and -Werror
command line options. They will cause ClangFormat to output any formatting violations to stdout and return a non-zero exit status if any input file was not correctly formatted.
$ clang-format --dry-run --Werror foo.cpp
foo.cpp:129:23: error: code should be clang-formatted [-Wclang-format-violations]
if (rc <= 0) {
$ echo $?
1
Originally from my website here: https://rigtorp.se/notes/clang-format/
Related Topics
Ruby: Sorting 2 Arrays Using Values from One of Them
Sinatra Doesn't Know This Ditty Even When Default Route Is Implemented with Modular Style
Ruby: How to Remove Items from Array a If It's Not in Array B
How to Make Private Activities
Setting Up a Polymorphic Association
How to Require Activerecord in Irb
Heroku-18: Git Push Fails. Showing Different Versions of Ruby on Push
Ruby Gets() Not Returning Correct String
Ruby on Rails - Helper Method - Undefined Method 'Log_In' in Ruby on Rails
To_SQL Not Working on Update_Attributes or .Save
Heroku Deplyoment Asset Precompiling Failed on Rails 6
Attr_Accessor, Not Able to Access Property
Ruby, MAC, Geektool Question, File Access Rights
Importing CSV as Test Data in Cucumber
Rails + Google Calendar API Events Not Created
Using Sed to Append Lines to File During Vagrant Provisioning