我想将一些文件提取到一个新的仓库,保留其历史记录,包括重命名的文件。
我能找到的最好和最接近的答案是new-repo-with-copied-history-of-only-currently-tracked-files,使用git filter-branch --index-filter
。它成功保留了现有文件的历史记录,但不保留重命名文件的历史记录。
(我能找到的另一个答案是使用git filter-branch --subdirectory-filter
。但它有两个问题:似乎不适用于整个仓库(文件夹'。')并且不保留重命名文件的历史记录。)
(另一个答案是使用git subtree
。但它根本没有保留历史。)
所以我可能正在寻找一种方法来改进git ls-files > keep-these.txt
命令,从最接近的答案也列出所有以前的文件名。也许是剧本?
答案 0 :(得分:3)
Git不会存储文件名更改。
每个提交都存储一个完整的树,例如,可能提交1234567...
有文件README
和foo.txt
并提交fedcba9 ...有文件readme.txt
和{{1} }。如果你要求git将提交foo
与提交1234567
进行比较,并且fedcba9
与 1 与README
足够相似,那么git会说出来的方式将一个提交转换为另一个提交是重命名该文件。 (如果一个提交是另一个提交的父提交,则子提交的readme.txt
将显示重命名,因为git show
会在git show
时计算此更改。)
另一方面,如果第二个git show
文件太不相同,但readme
与README
非常相似,那么git会说改变foo
的方式实现1234567
是将fedcba9
重命名为README
。
关键是当你要求比较时,git会计算,而不是更早。提交之间没有任何内容表示"重命名某些文件"。 Git只是比较提交并决定然后文件是否足够相似。
出于您的目的,这最终意味着对于您提交复制或部分复制的每个提交,您必须确定要保留哪些路径名称以及要保留哪些路径名称丢弃。如何实现这一点主要取决于你。 foo
命令有一个git log
标志来激活有限数量的重命名检测,因为它从子提交向父母反向工作,--follow
自动尝试执行相同操作;您可以使用这些(一次一个路径名称)来提供表单的映射:
git blame
例如。但是没有内置任何东西可以做到这一点,并且它不会特别容易。我首先将 in: commits A..B C..D E..F
use path: dir/file.ext dir/frill.txt lib/frill.next
与git log --follow
或--raw
输出相结合,然后查看是否检测到任何有趣的重命名。如果存在,那么这些是提交边界,在这些边界中,您希望更改在提交时保留和丢弃的路径(无论是--name-status
还是filter-branch
或者git diff --name-status
其他一些方法)。
如果这不起作用,或者您需要更多控制,请考虑在各种提交对之间运行git rev-list
(提交对信息来自git diff
)。
1 只要您要求重命名检测,"完全相同"是足够相似的,就像约有50%相似的东西一样。您可以使用提供给-M
builtin/var.c
标记的可选值调整所需的相似度。
修改:这似乎工作正常。我在git自己的$ git log --follow --raw --diff-filter=R --pretty=format:%H builtin/var.c
81b50f3ce40bfdd66e5d967bf82be001039a9a98
:100644 100644 2280518... 2280518... R100 builtin-var.c builtin/var.c
55b6745d633b9501576eb02183da0b0fb1cee964
:100644 100644 d9892f8... 2280518... R096 var.c builtin-var.c
上使用它,以前有两个以前的名字:
--diff-filter
git log --follow --raw --diff-filter=R --pretty=format:%H builtin/var.c |
while true; do
if ! read hash; then break; fi
IFS=$'\t' read mode_etc oldname newname
read blankline
echo in $hash, rename $oldname to $newname
done
抑制所有内容但重命名输出,以便我们看到哪个提交似乎重命名该文件。把它变成更有用的东西需要更多的工作,但这可能会让你相当远:
in 81b50f3ce40bfdd66e5d967bf82be001039a9a98, rename builtin-var.c to builtin/var.c
in 55b6745d633b9501576eb02183da0b0fb1cee964, rename var.c to builtin-var.c
产生:
namespace foo.blah {
export function baz() {
console.log('hello');
}
}