避免文件混乱:Git 文件操作技巧
- 一、Git工作原理概述
- 二、删除文件
- 三、查看指定文件的修改
- [四、指定不需要 Git 管理的文件](#四、指定不需要 Git 管理的文件)
- 五、总结
一、Git工作原理概述
Git是一种分布式版本控制系统,其核心在于其高效的快照机制、强大的分支与合并功能、本地开发的灵活性。
-
数据结构:Git 将项目的历史记录看作是一个由多个快照组成的链条。每次提交,Git会捕捉当前文件状态并记录这段快照。
-
树和对象:Git使用三种主要类型的对象:Blob(文件内容)、Tree(目录结构)和Commit(提交记录)。每次提交都会生成一个Commit对象,指向一个Tree对象,该Tree对象又指向若干Blob对象。
-
本地操作:Git是分布式的,每个开发者的本地仓库都是一个完整的版本库,包含了项目的所有历史。开发者可以在本地进行提交、分支、合并等操作,而不需要联网。
-
分支管理:Git的分支操作非常轻量,可以快速创建、切换和合并分支。每个分支代表了一个独立的开发线,方便团队协作和功能开发。
-
数据完整性:Git使用SHA-1哈希值来唯一标识每个对象,提供强大的数据完整性保护。任何文件或历史记录的改变都会导致哈希值的变化,从而能够检测到数据是否被篡改。
-
暂存区:Git 引入了一个暂存区,允许开发者在提交之前选择要提交的更改。这使得开发者可以更精细地控制提交内容。
-
远程仓库 :虽然Git是分布式的,但它也支持远程仓库。开发者可以使用
git push
和git pull
命令将本地更改推送到远程仓库或从远程仓库拉取更新。
在进行任何文件操作之前,了解当前工作目录的状态是至关重要的。使用以下命令可以查看当前的文件状态:
bash
git status
这个命令将显示已修改、已添加和未跟踪的文件,便于了解需要处理的文件。
二、删除文件
进行代码重构,有些类已经不需要了,那对应的源码文件也应该删除,此时怎么操作?比如删除
timer.cpp
和timer.h
,这两个文件已经push
到远程仓库了。
想从 Git 中删除文件,可以使用git rm
命令。这个命令不仅会删除文件,还会将删除操作记录到版本控制中:
bash
git rm 文件名
操作步骤如下:
bash
git rm -rf timer.cpp timer.h
git commit --m "remove timer mudlue"
git push
有时希望只是从版本控制中删除文件,但保留本地副本。这时候可以使用--cached
选项:
bash
git rm --cached 文件名
要删除所有未跟踪的文件,可以使用git clean
命令。请小心使用,以免误删重要文件:
bash
git clean -f
有的时候可能会不小心上传了一些无用的文件,尤其是使用C和C++开发的同事,一不小心上传很多编译的中间文件,当然这个操作是可以通过.gitignore
来避免的;还有的时候可能是上传了一个秘钥文件,这样关键的东西一般是很保密的,一般开发人员不应该能看到这样的秘钥文件。那commit
且push
到远程仓库了,该怎么把它给删除呢?而且记录里也不应该存在,比如我们永久删除sort.hpp
:
bash
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch sort.hpp' --prune-empty --tag-name-filter cat -- --all
# sort.hpp也可以替换成文件夹, 此时要在git rm后添加-r参数
bash
git push origin master --force
# 从上图也能看出来远程仓库没有被修改
三、查看指定文件的修改
查看文件所有的commit
:
bash
git log --oneline filename # 显示文件的所有修改记录
示例:
bash
$ git log --oneline src/flyMemTest.cc
ac75ee8 (HEAD -> master) Optimize log and print.
53cc38f (origin/master, origin/HEAD) Add Configures class and modify makeFile.
a60663f feat: add test0 algorithm
3235113 optimized code
71d5555 optimize code
1be415f Add os class and update src
66f95bb feat: add asynLogger class
5a29202 feat:update JsonValue and JsonParser
909a271 feat:add src file(JsonValue,JsonParser)
查看所有commit
的修改内容:
bash
git log --p filename # 显示所有commit的修改
示例:
查看某个commit
里的修改:
bash
git show commit-id filename # 显示某个commit里文件的修改
查看本地修改的差异:
bash
git diff filename # 查看本地对某个文件做了那些具体修改
与某个commit
做比较:
bash
git diff commit-id filename
# 显示与某个commit间所有的差异,commit-id可以替换成HEAD,比如HEAD~2
两个commit
间的差异:
bash
git diff commit-id1 commit-id2 # 显示两个commit所有的差异
四、指定不需要 Git 管理的文件
在使用 Git 的时候,对于 java 和 c/c++ 类的程序员尤其会遇到一件事情,就是使用git add .
的时候或者其它命令的时候会把编译生产的中间文件,比如.class
,.obj
,.o
等文件提交到库里。Git使用一个.gitignore
文件来定义规则,用于忽略那些文件不提交到 Git 中去。
.gitignore
可以提交到远程仓库中,这样这些规则就可以共享给所有的开发人员了,在.gitignore
文件中每一行都定义了忽略的规则,比如:
bash
*.[oa]
*~
第一行就是表示忽略所有的以.o
或者.a
结尾的文件,第二行表示忽略所有的以"~
"结尾的文件。
在使用.gitignore
时,一般遵循这么一个规则:
- 忽略操作系统自动生成的文件,比如缩略图等;
- 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如
Java
编译产生的.class
文件,比如c++
的.obj
文件; - 忽略自己的带有敏感信息的配置文件,比如存放口令的配置文件,比如日志文件等。
那这个.gitignore
文件按照什么样的规则去定义的呢?
-
空格不匹配任意文件,可作为分隔符,可用反斜杠转义。
-
以"
#
"开头的行都会被 Git 忽略。即#
开头的文件标识注释,可以使用反斜杠进行转义。 -
可以使用标准的
glob
模式匹配。所谓的glob
模式是指shell
所使用的简化了的正则表达式。 -
以斜杠"
/
"开头表示目录;"/"结束的模式只匹配文件夹以及在该文件夹路径下的内容,但是不匹配该文件;"/
"开始的模式匹配项目跟目录;如果一个模式不包含斜杠,则它匹配相对于当前.gitignore
文件路径的内容,如果该模式不在.gitignore
文件中,则相对于项目根目录。比如:/TODO
:表示仅仅忽略repo
跟目录下的TODO
文件,不包含子目录下的TODO
文件。/build/
:表示忽略整个build
目录及其下的所有文件。bin/
:表示忽略当前目录下的bin目录及其下所有的文件,bin
文件不会被忽略。build.sh
:表示忽略当前目录下的build.sh
文件。
-
以星号"
*
"通配多个字符,即匹配多个任意字符;使用两个星号"**
" 表示匹配任意中间目录。比如:doc/*.txt
:表示忽略当前doc
目录下的所有的以.txt
结尾的文件,但是doc/design/arch.txt
文件不会被忽略掉。/*.c
:表示忽略根目录下的所有的.c
文件。build/*.obj
:表示忽略build目录下的所有.obj
文件,但是build/http/http_core.obj
不会忽略掉。build/**/*.obj
:表示忽略build
目录,及其子目录,及其子目录的子目录和子子目录等等下的所有.obj
文件。**/*.a
:表示忽略所有目录下的.a
文件,*.a
/bin/*
:表示忽略/bin/
下的全部文件,不包含/bin/rtmp/hello
文件。bin/*
:表示忽略所有文件路径带有bin
字符串的文件,比如/bin/
,/bin/subdir/
等目录下的内容都会被忽略。
-
以问号"
?
"通配单个字符,即匹配一个任意字符。 -
以方括号"
[]
"包含单个字符的匹配列表,即匹配任何一个列在方括号中的字符。比如[abc]
表示要么匹配一个a
,要么匹配一个b
,要么匹配一个c
;如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配。比如[0-9]
表示匹配所有0
到9
的数字,[a-z]
表示匹配任意的小写字母)。 -
以叹号"
!
"表示不忽略(跟踪)匹配到的文件或目录,即要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!
)取反。需要特别注意的是:如果文件的父目录已经被前面的规则排除掉了,那么对这个文件用"!
"规则是不起作用的。也就是说"!
"开头的模式表示否定,该文件将会再次被包含,如果排除了该文件的父级目录,则使用"!
"也不会再次被包含。可以使用反斜杠进行转义。bash#下面两条规则一起就是忽略掉/mtk/目录下所有的文件,但是不忽略/mtk/protocol.txt文件 /mtk/* !/mtk/protocol.txt #下面这两条规则表示忽略掉/mtk/目录下所有内容,也忽略掉/mtk/protocol.txt文件 /mtk/ !/mtk/protocol.txt
推荐一个自动生成 .gitignore
文件的网址:http://www.gitignore.io/。
五、总结
掌握好的Git文件管理技巧,可以让你的开发过程更加顺畅和高效。利用这些命令和方法,你可以轻松地管理文件,删除不必要的内容,以及忽略那些不需要跟踪的文件与文件夹。希望本文能帮助到你,让你的Git使用体验更上一层楼!