Git基于内容而没有文件,因此我目前了解以下行为,但我想知道是否有特殊选项或黑客来检测此类内容:
git init
mkdir -p foo/bar
echo "test" foo/a.txt
echo "test2" foo/bar/b.txt
git add -A
git commit -m "test"
rm -fr foo
git add -A
git commit -m "delete whole dir"
git log --name-status
当我查看日志时,Git
不会清楚地告诉我foo
已被删除,但所有文件foo/a.txt
和foo/bar/b.txt
都已删除
commit d1513a9b36cd546371a194e798566c49e779e3a9
Date: Tue Sep 8 16:58:21 2015 +0200
delete whole dir
D foo/a.txt
D foo/bar/b.txt
commit 135f7ae52dfddcee5eeb7bdfa9f0d5c924fed3af
Date: Tue Sep 8 16:58:10 2015 +0200
test
A foo/a.txt
A foo/bar/b.txt
因此,如果我创建以下提交:
mkdir -p foo/bar
echo "test" > foo/a.txt
echo "test2" > foo/bar/b.txt
echo "test3" > foo/bar/c.txt
git add -A
git commit -m "test2"
rm -f foo/a.txt foo/bar/b.txt
git add -A
git commit -m "delete just 2 files"
git log --name-status
提交name-status
和delete whole dir
之间的 delete just 2 files
类似
commit 92564fb59464fd6bba2766a6d488c2ff8ca967ea
Date: Tue Sep 8 17:03:09 2015 +0200
delete just 2 files
D foo/a.txt
D foo/bar/b.txt
commit 3b13f27e960c4ec66464e8a1e0d23f038a872564
Date: Tue Sep 8 17:02:50 2015 +0200
test2
A foo/a.txt
A foo/bar/b.txt
A foo/bar/c.txt
删除整个目录时有没有办法检测差异?
答案 0 :(得分:3)
假设您的存储库中的示例树结构为:
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: a/b/c/d/e/q.txt
new file: a/b/c/m.txt
new file: a/b/c/n.txt
new file: a/b/f/o.txt
new file: a/b/f/p.txt
new file: a/b/k.txt
new file: a/b/z.txt
new file: a/x.txt
new file: a/y.txt
让我们进行以下提交:
commit 0bb4d4d50072c1eac1c3cb2b14b670deba8ee31b
Author: Site User <user@site.com>
Date: Tue Sep 8 19:27:58 2015 +0100
removed a/b/c/d/e/q.txt
D a/b/c/d/e/q.txt
-
commit 3b53f16eb2fd7d3d605180ccabcfa71eb9e9225a
Author: Site User <user@site.com>
Date: Tue Sep 8 19:28:55 2015 +0100
removed a/b/c/m.txt and a/b/c/n.txt (full a/b/c)
D a/b/c/m.txt
D a/b/c/n.txt
-
commit 3af8ace473944996fb8b21135106360305e8b89a
Author: Site User <user@site.com>
Date: Tue Sep 8 19:30:30 2015 +0100
added a/b/g/w.txt
A a/b/g/w.txt
-
提交3b53f16eb2fd7d3d605180ccabcfa71eb9e9225a是查看文件夹&#34; a / b / c&#34;消失,因为它中的最后一个文件被删除。
要在删除文件夹a / b / c时找到提交的SHA#,您可以找到涉及&#34; a / b / c&#34;的最后一次提交。使用以下组合的文件夹:
#> git log --name-status -- a/b/c
和
#> git ls-tree -r [commit] -- a/b/c
类似:
for cmt in $(git log --pretty=%H -- a/b/c); \
do X=$(git ls-tree -r "${cmt}" -- a/b/c); \
[[ -z "${X}" ]] && echo "The folder a/b/c has been deleted in commit: ${cmt}"; \
done
<强>输出:强>
The folder a/b/c has been deleted in commit: 3b53f16eb2fd7d3d605180ccabcfa71eb9e9225a
以简单BASH脚本的形式(我将其命名为deleted.sh,应具有可执行权限):
#!/bin/bash
P="$1"
GIT=$(which git)
for cmt in $($GIT log --pretty=%H -- "${P}"); do
X=$($GIT ls-tree -r "${cmt}" -- "${P}");
[[ -z "${X}" ]] && echo "The folder a/b/c has been deleted in commit: ${cmt}";
done
<强>用法:强>
./deleted.sh a/b/c
<强>输出:强>
The folder a/b/c has been deleted in commit: 3b53f16eb2fd7d3d605180ccabcfa71eb9e9225a
如何运作
第一次提交,在历史记录中回溯,在树中没有与文件夹路径匹配的文件,应该这样做。
这就是shell脚本正在做的事情。
它在历史中向后迭代,检索与文件夹中的任何文件相关的所有SHA#,然后在这些提交中找到第一个,没有任何文件与提供的路径匹配, Git树。
该提交即将出现在列表中以进行检查,确保其中存在涉及该文件夹的更改。
没有与其树中的文件夹匹配的文件(已过滤&#34; ls-tree&#34;返回空字符串),确保它是已删除该文件夹中le last文件的提交
答案 1 :(得分:1)
据我所知,没有特殊的git命令来检测目录是否已被删除/移动。
但是,如果整个目录已移至跟踪的git存储库中的新位置,则它应显示在Untracked files:
命令的git status
部分下。此外,它的所有文件都将显示为已删除。
对于已删除的目录,如果您希望该目录不再存在,则可以运行ls
命令以仔细检查该目录是否已被删除。如果目录不在那里,则不会被跟踪。
如果目录存在但不包含任何内容,那么git也不会跟踪它。不过,你可以试试
git ls-files dirName/ --error-unmatch; echo$?
此解决方案最初在this StackOverflow question上提及。该命令应该检查git是否正在跟踪某个特定文件,但在这种情况下,git将检查是否存在dirName
是文件路径的一部分的文件。如果没有跟踪文件夹,则会显示错误。