git命令有一个有用的命令,可以在重命名后跟踪文件,如git log --follow path/to/some/file
中所示。不幸的是,它仅适用于单个文件。我希望能够做到等同于git log --follow some/directory
。
这样做的一种方法可能是按下git ls-tree
的输出并在循环中执行此操作,但问题就变成了影响多个文件的提交不会“合并”到一个提交中。 / p>
有更好的方法吗?注意:使用git 2.7.4
答案 0 :(得分:4)
没有
Git不存储目录,只存储文件。当您使用任何路径名来查看整个提交的git log
或git diff
之类的命令时,Git实际上会说“从整个提交开始,然后将其缩小到匹配该路径的文件”。这里的目录只是最终选择目录中的每个文件。
--follow
选项只能跟随一个文件。因此,如果您能够以某种方式设法将其应用于目录,Git会首先将目录转换为一组文件,然后选择其中一个文件并按照该文件。
(实际的--follow
代码是非常hacky。它利用了重命名检测代码,但只有在以较新到旧的顺序比较提交时才有效:如果添加--reverse
, --follow
永远不会工作。可能整个事情需要被抛弃并重新编码。也许通过重新编码,你可以让它处理多个文件名,甚至是满是文件的目录。)
答案 1 :(得分:0)
似乎没有内置的方法来做到这一点。
可以使用脚本并遵循一个简单的算法来做到这一点:
这是使用python 3和sh
模块执行此操作的一种hacky方式,由于各种原因无法在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 %s\n' % (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/*