带有预提交钩子的 Git 提交,为什么会得到不同的结果?

问题描述

我有一个预提交钩子来运行 python 脚本,该脚本将修改暂存文件并在脚本末尾使用 git add . 重新添加这些文件

预提交看起来像这样:

#!/bin/sh
python2.7 .git/hooks/editfile.py

python 脚本如下所示:

import os
import mmap
import sys
import subprocess

def getmodifiedfiles():
  files = []
  args = ['git','diff','HEAD','--name-only','-r','--diff-filter=M']
  with open(os.devnull,'w') as b:
     files = subprocess.check_output(args,stderr=b).splitlines()

  files = [i for i in files if os.path.isfile(i)]
  return files

def updaterevision(line):
    strVer = line.split("$Revision: ")[1].split()[0]
    version = [x for x in strVer.split('.')]
    ver = [int(i) for i in version]

    if ver[1] == 99:
      ver[0] += 1
      ver[1] = 0
    else:
      ver[1] += 1

    strVer = "%d.%02d" % (ver[0],ver[1])
    return str.replace(line,line.split("$Revision: ")[1].split()[0],strVer)

def main(args):
  filelist = getmodifiedfiles()  
  
  for file in filelist :
    lines = open(file).readlines()

    i = 0
    for line in lines:
        if '$Revision:' in line:
          lines[idx] = updaterevision(line)
        
        i += 1

  with open(file,'w') as r:
    r.writelines(lines)          

  args = ['git','add','.']
  subprocess.call(args)
  
if __name__ == '__main__':
    main(sys.argv)

它与 git commit -m "msg" 命令一起按预期工作,当 git status 我得到以下结果时:

On branch master
Your branch is ahead of 'origin/master' by 1 commit.

nothing to commit (working directory clean)

但是如果使用 git commit <filename>git commit -m "msg" <filename> 提交,我得到了我不想要的以下结果:

On branch master
Changes to be committed:
   (use "git reset HEAD <file>..." to unstage)

   modified:   filename.py

Changes not staged for commit:
   (use "git add <file>..." to update what will be committed)
   (use "git checkout -- <file>..." to discard changes in working directory)

   modified:   filename.py

有什么不同?我不想修复用户只使用第一个命令来提交。有什么想法吗?

解决方法

不幸的是,对于您的文件重写预提交挂钩,您唯一能做的就是远离 git commit <files...> 并仅使用 git-add-then-git-commit。>

也就是说,您并非完全没有希望。由于您的钩子脚本旨在重写文件(设置“版本信息”),因此使用过滤器是一个更好的主意。

看看这个答案:https://stackoverflow.com/a/17360528/5958455

基本上,您将脚本设置为“干净过滤器”,以便在匹配文件暂存时应用它。幸运的是,这包括您的 git commit <file...> 用例。