git还原文件权限
程序员文章站
2024-03-04 09:37:53
...
1. 绪言
- 还是啰嗦的讲一下吧~项目开发的时候,新开了一个分支,不知道为啥,将大部分文件的权限都改成了755。github上的提示如下:
- 自己算是git小白啦,就会
clone
、add
、commit
、push
、pull
、merger
等基本的操作,每次看commit之后的变化,都是直接看网页上的。完全不懂使用git diff
命令。 - 奈何老板是个技术流,每次使用git diff命令查看内容变化,一大推的file mode change的提示,让他觉得很烦。这不,下达命令了,让我们给解决了,将文件改回之前的权限。
diff --git a/vendor/github.com/gogo/protobuf/AUTHORS b/vendor/github.com/gogo/protobuf/AUTHORS
old mode 100644
new mode 100755
- 问题来了,这不是已经commit过的内容吗?会一直留在log中啊,何来去除一说?原因: 估计这就是因为我们不怎么使用
git diff
命令导致的吧。如果使用git diff
命令,我们会发现如果恢复了原本的权限,上面的内容就会消失,不会影响我们阅读commit之间的差异!
2. 讲讲linux的文件权限
- 使用
ls - al
可以查看文件的权限,我们关注第一串字符,共10个。
drwxr-xr-x 2 hadoop hadoop 4096 11月 10 13:32 模板
- 字符的含义如下:
① 第一个字符代表文件(-
)、目录(d
),链接(l
)
② 其余字符每3个一组(rwx),读(r)、写(w)、执行(x)
(1)第一组rwx
:表示文件所有者的权限(用户权限u
)是读、写和执行
(2)第二组rw-
:与文件所有者同一组的用户的权限(组权限g
)是读、写但不能执行
(3)第三组r--
:不与文件所有者同组的其他用户的权限(不同组其他用户权限o
)是只读,不能写和执行
③ 可以使用chmod
设置文件权限,其中每组的rwx都可以看做二进制的1或者0。比如rwxr-xr-x
表示111 101 101
,所以换算成10进制就是755。chmod 755 1.txt
命令便表示:为1.txt这个文件赋权限为755。
④ 也可以使用chmod +、-、=
设置权限,最基础的是644。原本一个文件权限为644(rw-r--r--)
,通过chmod +x
就变成rwxr-xr-x
,即755
.
⑤ 注意:chmod +x
和chmod a+x
是一样的,一般没有明确要求,可以就用chmod +x
。而chmod +x
和chmod u+x
的是不一样的,后者只为所有者设置了可执行权限。
- 我们这次遇到的
file mode
跟linux 中的又不太一样,因为他多了100。其实100表示普通文件
,其他常见类型如下所示:0100000000000000
(040000
): Directory1000000110100100
(100644
): Regular non-executable file1000000110110100
(100664
): Regular non-executable group-writeable file1000000111101101
(100755
): Regular executable file1010000000000000
(120000
): Symbolic link1110000000000000
(160000
): Gitlink - 之后可以使用如下命令让git忽略文件权限的改变,可以在
.git/config
中查看到相关设置是否生效。
git config --add core.filemode false
参考链接:
linux下chmod +x的意思?为什么要进行chmod +x
Linux下用户组、文件权限详解
git file mode change
3. 老板给的解决方法
- 老板直接在github中添加注释,告诉了我们解决办法。我只看得懂
|
之前的部分和chmod
,后面的xargs
和-x
就让我蒙圈了。后来询问了技术流的师兄,耐心给我做了解答,终于知道含义了。
find . -name *.go | xargs chmod -x
- 师兄给的解决办法,应该是一样的效果,只是多了
-executable
选项,表示查找有执行权限的go文件。
find . -name `*.go` -executable | xargs chmod -x
-
find . -name *.go
用于查找到我们想要恢复权限的go文件。
① 关于xargs
- 在日常处理中,某些命令需要使用前一命名的输出作为命令参数进行输入,但是这些命令缺不支持通过管道
|
传输数据,这时候可以使用xargs命令去实现。 - 我们先看看下面的两个命令,就多了一次xargs,怎么结果千差万别呢。一个把
'--help'
作为了cat需要展示的文件内容,一个把'--help'
,作为了cat的选项。
$ echo '--help' | cat
--help
$ echo '--help' | xargs cat
用法:cat [选项]... [文件]...
Concatenate FILE(s) to standard output.
如果没有指定文件,或者文件为"-",则从标准输入读取。
-A, --show-all equivalent to -vET
-b, --number-nonblank number nonempty output lines, overrides -n
-e equivalent to -vE
-E, --show-ends display $ at end of each line
-n, --number number all output lines
-s, --squeeze-blank suppress repeated empty output lines
-t 与-vT 等价
-T, --show-tabs 将跳格字符显示为^I
-u (被忽略)
-v, --show-nonprinting 使用^ 和M- 引用,除了LFD和 TAB 之外
--help 显示此帮助信息并退出
--version 显示版本信息并退出
示例:
cat f - g 先输出f 的内容,然后输出标准输入的内容,最后输出g 的内容。
cat 将标准输入的内容复制到标准输出。
-
echo '--help' | cat
该命令输出的是echo的内容,也就是说将echo的内容当作cat处理的文件内容了,实际上就是echo命令的输出通过管道定向到cat的输入了。然后cat从其标准输入中读取待处理的文本内容。这等价于在test.txt文件中有一行字符'--help'
然后运行cat test.txt
的效果。 -
echo '--help' | xargs cat
等价于cat --help
。就是xargs将其接受的字符串 --help 做成cat的一个命令参数来运行cat命令 ,同样echo 'test.c test.cpp' | xargs cat
等价于cat test.c test.cpp
此时会将test.c和test.cpp的内容都显示出来。 - 经常将find命令查找到文件传递给xargs命令,由xargs命令将这些文件作为后续命令的参数并运行后续命令。
② 整个命名的意思
- 通过对
chmod -x
和xargs
命令的分析,其实整个命令就是想通过find查找到所有的go文件,然后将这些go文件的权限去掉可执行权限,让其从755恢复成644。 - 如果想让其从644恢复成755,改为
chmod +x
就可以了。
参考链接:
xargs命令详解,xargs与管道的区别
linux之find命令详解
3. 问题的解决
- 在项目目录下执行
find . -name *.go | xargs chmod -x
命令, 就可以恢复go文件的权限。其他文件照葫芦画瓢就可以。 - 执行完以后,通过以下命令进行提交(这是师兄告诉的)。
git add -u # -u, --update, 更新已跟踪的文件
git commit -m ”XXXX“
git push -u origin test
- 师兄还叮嘱我一定要注意为什么加上了可执行权限,不然之后还可能出现这样的问题。超级认真,不愧是技术流大佬!
4. 那么多类型的文件需要该权限,添麻烦了
- 除了go文件,还有很多
.md、.yml、.json
等常见类型的文件,关键还有很多不常见类型的文件。不仅文件类型这么多,还有一些go文件人家本身是755的,由于我的操作,变成了644。。。通过find命令何时才能处理完? - 清华的小伙伴就用go语言做起了diff的结果解析,判断文件mode,写出了设立了脚本进行处理。真的是大佬啊!
package main
import (
"bufio"
"fmt"
"io"
"os"
"strings"
)
func main() {
fi, err := os.Open("diff.out")
if err != nil {
panic(err)
}
defer fi.Close()
var diff string
var oldMode string
br := bufio.NewReader(fi)
for {
line, _, err := br.ReadLine()
if err == io.EOF {
break
}
if strings.HasPrefix(string(line), "diff --git") {
diff = strings.Replace(string(line), "diff --git ", "", 1)
diff = strings.Split(diff, " ")[0]
diff = strings.Replace(diff, "a/", "", 1)
}
if strings.HasPrefix(string(line), "old mode 100") {
oldMode = strings.Replace(string(line), "old mode 100", "", 1)
}
if strings.HasPrefix(string(line), "new mode 100") {
fmt.Println(fmt.Sprintf("chmod %s %s", oldMode, diff))
}
}
}
- 运行的时候可以将输出重定向如
go run main.go > mode.sh
,然后再项目目录下运行mode.sh即可使得所有的文件mode和master一致。 - 附加链接:Git diff 常见用法
上一篇: html知识点