Git pre-push hook to reject string addition in overall changes

血红的双手。 提交于 2019-12-24 06:10:24

问题


How would you write a pre-push hook that rejects pushing when the overall diff introduces a specific word/sentence/string?

Motivating use-case:

  1. committing TODO notes (marking tasks to complete before pushing)
  2. letting git prevent me from forgetting to address said notes when pushing

Notes:

  1. I have seen a lot of different questions and answers but none come close. The ones that try quickly fail on edge cases (e.g. this and this).
  2. notice that "overall diff" means that commits adding TODO would be allowed as long as the string was removed in subsequent commits being pushed (such that the overall delta did not contain it)
  3. the main difficulty is finding a range to pass to git diff that works in all cases.
  4. only additions of TODO are to be blocked, removals should be allowed in the diff
  5. modifications of lines previously containing TODO that maintain it, imply a TODO addition (even if simultaneous with a removal) and should therefore be blocked (rationale: no objective way to distinguish whether the introduced TODO is the same as the removed one).
  6. such a hook should cope with all valid pushes, checking only deltas corresponding to ranges of new commits (e.g. nothing to check in push --delete). Some particular cases to consider:
    • new branches
    • deleted branches
    • renamed branches
    • branching off of something other than master (so no merge-base origin/master)
    • splits/merges
    • tags
    • force pushes
  7. Bonus variation: prevent pushing any commits adding TODO (rather than in the overall diff).

回答1:


Could try something like the following.

#!/usr/bin/env ruby

branchName = `git rev-parse --abbrev-ref HEAD`.strip
log = `git reflog show --no-abbrev #{branchName} --format='\%h'`.split("\n")
range = "#{log.last}..#{log.first}".gsub("'", "")

`git diff --name-only --diff-filter=ACMR #{range}`.each_line do |file|
  file = file.chomp
  command = "git show #{log.first}:#{file}".gsub("'", "")
  content = `#{command}`

  if ( content =~ /TODO/ )
    puts "'#{file}' contains TODO"
    exit 1
  end
end

exit 0

This will search the content of any new, added, modified, or renamed files for the word TODO. If it finds the word it will exit and output the name of the file that contains the matching regex.

This will work for new branches, but it does have issues if you rebase your branch as in that case it may pull in other people's changes.



来源:https://stackoverflow.com/questions/54480609/git-pre-push-hook-to-reject-string-addition-in-overall-changes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!