Git如何检测整个文件夹删除/移动 [英] Git how to detect whole folder deleted/moved

查看:214
本文介绍了Git如何检测整个文件夹删除/移动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆