跟随一个已经重命名的目录?

git命令有一个有用的命令来跟踪重命名后的文件,如在git log --follow path/to/some/file 。 不幸的是,它只适用于单个文件。 我希望能够做到相当于git log --follow some/directory

这样做的一种方式可能是按摩git ls-tree的输出并在循环中执行该操作,但问题在于影响多个文件的提交不会“合并”为一个提交。

有没有更好的方法来做到这一点? 注意:使用git 2.7.4


没有。

Git不存储目录,只存储文件。 当你使用任何路径名来查看整个提交的git loggit diff命令时,Git实质上是说“从整个提交开始,然后将其缩小到与该路径匹配的文件”。 这里的目录只是简单地选择目录中的每个文件。

- --follow选项只能跟随一个文件。 因此,如果你能以某种方式设法将它应用到目录中,Git会首先将目录转换为一组文件,然后选择其中一个文件并遵循该文件。

(实际 - --follow代码非常黑客,它利用了重命名检测代码,但只在提交按照新旧顺序进行比较时才起作用:如果添加--reverse ,-- --follow永远不会工作。可能整个事情都需要被抛出并重新编码,也许通过重新编码它,你可以使它处理多个文件名,甚至可以处理多个文件。)


似乎没有一种内在的方式来做到这一点。

可以使用脚本并遵循一个简单的算法来完成此操作:

  • 为每个文件生成一个与之相关的提交列表
  • 合并所有列表并对它们进行稳定的排序(这很棘手,因为确定提交的顺序并不简单)
  • 迭代执行每个提交的git日志,并通过更少的管道
  • 下面是一个使用python 3和sh模块的方法,因为各种原因在Windows上无法运行。

    #!/usr/bin/env python3
    
    import os
    import shlex
    import sys
    import tempfile
    
    import sh
    
    def _get_commits(fname):
        # Ask for the commit and the timestamp
        # .. the timestamp doesn't guarantee ordering, but good enough
        for c in sh.git('log', '--follow', '--pretty=%ct %h', fname,
                       _tty_out=False, _iter=True):
            c = c.strip().split()
            yield int(c[0]), c[1]
    
    def git_log_follow_multi(filenames):
        if len(filenames) == 0:
            print("Specify at least one file to log")
        elif len(filenames) <= 1:
            os.system('git log --follow -p %s' % filenames[0])
        else:
            # Use git log to generate lists of commits for each file, sort
            commits = []
            for fname in filenames:
                commits += _get_commits(fname)
    
            # Sort the lists (python's sort is stable)
            commits.sort(reverse=True)
    
            # Uniquify (http://www.peterbe.com/plog/uniqifiers-benchmark)
            seen = set()
            seen_add = seen.add
            commits = [c for c in commits if not (c in seen or seen_add(c))]
    
            # Finally, display them
            tname = None
    
            try:
                file_list = ' '.join(shlex.quote(fname) for fname in filenames)
    
                with tempfile.NamedTemporaryFile(mode='w', delete=False) as fp:
                    tname = fp.name
                    for _, commit in commits:
                        fp.write('git log -p -1 --color %s %sn' % (commit, file_list))
    
                # Use os.system to make our lives easier
                os.system('bash %s | less -FRX' % tname)
            finally:
                if tname:
                    os.unlink(tname)
    
    
    if __name__ == '__main__':
        git_log_follow_multi(sys.argv[1:])
    

    现在,这个脚本并不完全满足您的需求,因为它需要一个文件列表,但您可以使用glob来执行它,并且它会执行您要查找的内容。

    ./script.py src/*
    
    链接地址: http://www.djcxy.com/p/92785.html

    上一篇: follow a directory which has been renamed?

    下一篇: How to dynamically create a menu bar based on JSON using Angular Material?