Git如何检测整个文件夹删除/移动 [英] Git how to detect whole folder deleted/moved
问题描述
Git基于内容并且没有文件,因此我目前了解以下行为,但我想知道是否有特殊选项或黑客来检测此类事情:
git init
mkdir -p foo / bar
echotestfoo / a.txt
echotest2foo / bar / b.txt
git add -A
git commit -mtest
rm -fr foo
git add -A
git commit -m删除整个dir
git log --name-status
当我检查日志时, Git
不会清楚地表明 foo
已被删除,但所有文件 foo / a.txt
和 foo / bar / b.txt
已被删除
commit d1513a9b36cd546371a194e798566c49e779e3a9
日期:星期二9月8日16:58:21 2015 +0200
删除整个目录
D foo / a.txt
D foo / bar / b.txt
提交135f7ae52dfddcee5eeb7bdfa9f0d5c924fed3af
日期:星期二9月8日16:58:10 2015 +0200
测试
a foo / a.txt
A foo / bar / b.txt
因此,如果我创建了以下提交:
mkdir -p foo / bar
echotest> foo / a.txt
echotest2> foo / bar / b.txt
echotest3> foo / bar / c.txt
git add -A
git commit -mtest2
rm -f foo / a.txt foo / bar / b.txt
git add -A
git commit -m删除2个文件
git log --name-status
名称状态
提交删除整个目录
和删除只有2个文件
类似
commit 92564fb59464fd6bba2766a6d488c2ff8ca967ea
日期:9月8日星期二17:03:09 2015 +0200
删除2个文件
D foo / a.txt
D foo / bar / b.txt
commit 3b13f27e960c4ec66464e8a1e0d23f038a872564
日期:9月8日星期二17:02:50 2015 +0200
test2
a foo / a.txt
a foo / bar / b.txt
A foo / bar / c.txt
当整个目录被删除时,有什么方法可以检测到差异吗? 您的存储库为:
初始提交
要提交的更改:
(使用git rm --cached< file> ...停用)
新文件:a / b / c / d / e / q.txt
新文件:a / b / c / m.txt
新文件:a / b / c / n。 txt
新文件:a / b / f / o.txt
新文件:a / b / f / p.txt
新文件:a / b / k.txt
新文件:a / b / z.txt
新文件:a / x.txt
新文件:a / y.txt
让我们进行下面的提交:
commit 0bb4d4d50072c1eac1c3cb2b14b670deba8ee31b
作者:网站用户< user@site.com>
日期:9月8日星期二19:27:58 2015 +0100
删除a / b / c / d / e / q.txt
D a / b / c / d / e / q.txt
-
提交3b53f16eb2fd7d3d605180ccabcfa71eb9e9225a
作者:网站用户< user@site.com>
日期:9月8日星期二19:28:55 2015 +0100
删除了a / b / c / m.txt和a / b / c / n.txt(全部a / b / c)
D a / b / c / m.txt
D a / b / c / n.txt
-
提交3af8ace473944996fb8b21135106360305e8b89a
作者:Site User< ; user@site.com>
日期:9月8日星期二19:30:30 2015 +0100
新增a / b / g / w.txt
a a / b / g / w.txt
< - > -
提交3b53f16eb2fd7d3d605180ccabcfa71eb9e9225a是看到文件夹a / b / c消失的那个文件夹,因为文件夹中的最后一个文件被删除。
文件夹a / b / c已被删除,您可以通过以下方式找到涉及a / b / c文件夹的最后提交:
#> git log --name-status - a / b / c
和
#> git ls-tree -r [commit] - a / b / c
:$(git log --pretty =%H - a / b / c)中的cmt的
; \
do X = $(git ls-tree -r$ {cmt} - a / b / c); \
[[-z$ {X}]]&& echo文件夹a / b / c已经在提交中删除:$ {cmt}; \
完成
输出:
文件夹a / b / c已在提交中删除:3b53f16eb2fd7d3d605180ccabcfa71eb9e9225a
以一种简单的BASH脚本(我的名字为deleted.sh,应该具有可执行权限):
#!/ bin / bash
P =$ 1
GIT = $(哪个git)
$ b $($ Git log --pretty =%H - $ {P});做
X = $($ GIT ls-tree -r$ {cmt} - $ {P});
[[-z$ {X}]]&& echo文件夹a / b / c已经在提交中删除:$ {cmt};
完成
用法:
./ deleted.sh a / b / c
输出:
文件夹a / b / c已被删除提交:3b53f16eb2fd7d3d605180ccabcfa71eb9e9225a
工作原理
历史上的第一次提交,在树中没有与文件夹路径匹配的文件,应该这样做。
这就是shell脚本正在做的事情。
它在历史中向后迭代,检索与文件夹中任何文件相关的所有SHA#,然后在这些提交中找到第一个,即没有任何文件与Git树中提供的路径相匹配。
这个提交将出现在列表中进行检查,确保其中涉及该文件夹的变化。
事实上,没有文件与树中的文件夹相匹配(过滤后的ls-tree返回一个空字符串),确保它是最后一个文件该文件夹中的文件已被删除。
Git is based on content and no file so I currently understand the following behavior but I want to know if there is a special option or hack to detect such thing:
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
When I check log, Git
will not clearly said me that foo
was deleted but all file foo/a.txt
and foo/bar/b.txt
was deleted
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
Thus if I create following commits:
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
between commit delete whole dir
and delete just 2 files
are similar
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
Is there any way to detect difference when whole directory is deleted?
Assuming a sample tree structure in your repository as:
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
Let's make the following commits:
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
-
Commit 3b53f16eb2fd7d3d605180ccabcfa71eb9e9225a is the one that sees the folder "a/b/c" disappear, as the last file in it is removed.
To find the SHA# of the commit when the folder a/b/c has been deleted, you can find the last commit involving the "a/b/c" folder by using a combination of:
#> git log --name-status -- a/b/c
and
#> git ls-tree -r [commit] -- a/b/c
Something like:
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
Output:
The folder a/b/c has been deleted in commit: 3b53f16eb2fd7d3d605180ccabcfa71eb9e9225a
In a form of simple BASH script (which I name deleted.sh, should have executable permissions):
#!/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
Usage:
./deleted.sh a/b/c
Output:
The folder a/b/c has been deleted in commit: 3b53f16eb2fd7d3d605180ccabcfa71eb9e9225a
How does it work
The first commit, going back in history, that has no files in tree matching the folder path, should do.
That is what the shell script is doing.
It iterates backwards in history, retrieving all of the SHA#s that are related to any files in the folder, and then finds - among those commits - the first, that does not have any files matching the path provided, in the Git tree.
The fact that that commit is coming up in the list to inspect, insures that there are changes, in it, that involve the folder.
The fact that there are no files matching the folder in its tree (filtered "ls-tree" returns an empty string), insures that it is the commit where le last file in that folder has been deleted.
这篇关于Git如何检测整个文件夹删除/移动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!