git初入门(二):文件操作
篇幅较长,可收藏防止迷路
0. 文件的四种状态
- Untracked: 未跟踪, 此文件在文件夹中, 但并没有加入到 git 库, 不参与版本控制. 通过
git add
状态变为Staged
. - Unmodify: 文件已经入库, 未修改, 即版本库中的文件快照内容与文件夹中完全一致. 这种类型的文件有两种去处, 如果它被修改, 而变为
Modified
. 如果使用git rm
移出版本库, 则成为Untracked
文件 - Modified: 文件已修改, 仅仅是修改, 并没有进行其他的操作. 这个文件也有两个去处, 通过
git add
可进入暂存staged
状态, 使用git checkout
则丢弃修改过, 返回到unmodify
状态, 这个git checkout
即从库中取出文件, 覆盖当前修改 - Staged: 暂存状态. 执行
git commit
则将修改同步到库中, 这时库中的文件和本地文件又变为一致, 文件为Unmodify
状态. 执行git reset HEAD filename
取消暂存, 文件状态为Modified
1. git init
代码语言:javascript复制 # 在当前目录新建一个Git代码库
git init
# 新建一个目录,将其初始化为Git代码库
git init [project-name]
2. git clone
代码语言:javascript复制 # 克隆一个项目和它的整个代码历史(版本信息)
git clone [url]
3. git status(查看文件状态)
代码语言:javascript复制 #查看指定文件状态
git status [filename]
#查看所有文件状态
git status
4. git add(添加文件与目录)
代码语言:javascript复制 # 添加指定文件到暂存区
$ git add [file1] [file2] ...
# 添加指定目录到暂存区,包括子目录
$ git add [dir]
# 添加当前目录的所有文件到暂存区
$ git add .
6. git reset
代码语言:javascript复制 #如果已经用add 命令把文件加入stage了,就先需要从stage中撤销
git reset HEAD <file>...
7. git clean
代码语言:javascript复制 # 移除所有未跟踪文件
# 一般会加上参数-df,-d表示包含目录,-f表示强制清除。
git clean [options]
8. git rm(移除文件与目录)
代码语言:javascript复制 #只从stage中删除,保留物理文件
git rm --cached readme.txt
#不但从stage中删除,同时删除物理文件
git rm readme.txt
#把a.txt改名为b.txt
git mv a.txt b.txt
9. git diff(查看文件修改后的差异)
代码语言:javascript复制 #查看文件修改后的差异
git diff [files]
---a 表示修改之前的文件, b 表示修改后的文件
#比较暂存区的文件与之前已经提交过的文件
git diff --cached
10. git checkout(签出)
代码语言:javascript复制 #用法一
git checkout [-q] [<commit>] [--] <paths>...
#用法二
git checkout [<branch>]
#用法三
git checkout [-m] [[-b]--orphan] <new_branch>] [<start_point>]
$ git checkout branch
#检出branch分支。要完成图中的三个步骤,更新HEAD以指向branch分支,以及用branch 指向的树更新暂存区和工作区。
$ git checkout
#汇总显示工作区、暂存区与HEAD的差异。
$ git checkout HEAD
#同上
$ git checkout -- filename
#用暂存区中filename文件来覆盖工作区中的filename文件。相当于取消自上次执行git add filename以来(如果执行过)的本地修改。
$ git checkout branch -- filename
#维持HEAD的指向不变。用branch所指向的提交中filename替换暂存区和工作区中相 应的文件。注意会将暂存区和工作区中的filename文件直接覆盖。
$ git checkout -- . 或写作 git checkout .
#注意git checkout 命令后的参数为一个点(“.”)。这条命令最危险!会取消所有本地的 #修改(相对于暂存区)。相当于用暂存区的所有文件直接覆盖本地文件,不给用户任何确认的机会!
$ git checkout commit_id -- file_name
#如果不加commit_id,那么git checkout -- file_name 表示恢复文件到本地版本库中最新的状态。
如:
代码语言:javascript复制 $ echo “123”>>hyy.txt
$ git add hyy.txt
$ echo "1" >> hyy.txt
$ git status
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: hyy.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: hyy.txt
$ git checkout hyy.txt # 取消了第3行的更改,使用暂存区里的hyy.txt覆盖了本地的hyy.txt
11. 忽略文件
有些时候我们不想把某些文件纳入版本控制中,比如数据库文件,临时文件,设计文件等
在主目录下建立 ".gitignore
" 文件,此文件有如下规则:
- 忽略文件中的空行或以井号(#)开始的行将会被忽略。
- 可以使用 Linux 通配符。例如:星号(*)代表任意多个字符,问号(?)代表一个字符,方括号(abc)代表可选字符范围,大括号({string1,string2,...})代表可选的字符串等。
- 如果名称的最前面有一个感叹号(!),表示例外规则,将不被忽略。
- 如果名称的最前面是一个路径分隔符(/),表示要忽略的文件在此目录下,而子目录中的文件不忽略。
- 如果名称的最后面是一个路径分隔符(/),表示要忽略的是此目录下该名称的子目录,而非文件(默认文件或目录都忽略)。
如:
代码语言:javascript复制 #
#为注释
*.txt #忽略所有 .txt结尾的文件
!lib.txt #但lib.txt除外
/temp #仅忽略项目根目录下的TODO文件,不包括其它目录temp
build/ #忽略build/目录下的所有文件
doc/*.txt #会忽略 doc/notes.txt 但不包括 doc/server/arch.txt
示例:
代码语言:javascript复制 # 忽略.log文件
$ echo "123">f1.log
$ echo "123">f2.log
$ echo "123">hyy03.txt
$ git add .
warning: LF will be replaced by CRLF in .gitignore.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in hyy03.txt.
The file will have its original line endings in your working directory
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: .gitignore
new file: hyy00.txt
new file: hyy02.txt
new file: hyy03.txt
通用的 java 忽视文件:
代码语言:javascript复制 # Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
idea 忽视文件:
代码语言:javascript复制 .idea/
*.iml
out/
gen/
idea-gitignore.jar
resources/templates.list
resources/gitignore/*
build/
build.properties
junit*.properties
IgnoreLexer.java~
.gradle
/verification
12. git commit(提交)
通过 add 只是将文件或目录添加到了 index 暂存区,
使用 commit 可以实现将暂存区的文件提交到本地仓库。
代码语言:javascript复制 # 提交暂存区到仓库区
$ git commit -m [提交说明信息]
# 提交暂存区的指定文件到仓库区
$ git commit [file1] [file2] ... -m [message]
# 提交工作区自上次commit之后的变化,直接到仓库区,跳过了add,对新文件无效
$ git commit -a
# 提交时显示所有diff信息
$ git commit -v
# 使用一次新的commit,替代上一次提交
# 如果代码没有任何新变化,则用来改写上一次commit的提交信息
$ git commit --amend -m [message]
# 重做上一次commit,并包括指定文件的新变化
$ git commit --amend [file1] [file2] ...
□ 提交
条件
代码语言:javascript复制 $ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: .gitignore
new file: hyy00.txt
new file: hyy02.txt
new file: hyy03.txt
提交:
代码语言:javascript复制 $ git commit hyy00.txt -m "指定提交hyy00.txt"
[master (root-commit) cbc3543] 指定提交hyy00.txt
1 file changed, 3 insertions( )
create mode 100644 hyy00.txt
提交后的状态:
代码语言:javascript复制 $ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: .gitignore
new file: hyy02.txt
new file: hyy03.txt
可以看到已经没有了hyy00.txt
□ 修订提交
如果我们提交过后发现有个文件改错了,或者只是想修改提交说明,这时可以对相应文件做出修改,将修改过的文件通过 "git add" 添加到暂存区,然后执行以下命令:
代码语言:javascript复制 #修订提交
$ git commit --amend <文件>
例子:
代码语言:javascript复制 $ git commit --amend hyy00.txt
[master f2cda26] dddddd指定提交hyy00.txt
Date: Sun Nov 28 13:41:42 2021 0800
1 file changed, 3 insertions( )
create mode 100644 hyy00.txt
□ 撤销提交(commit)
原理就是放弃工作区和 index 的改动,同时 HEAD 指针指向前一个 commit 对象
代码语言:javascript复制 #撤销上一次的提交
git reset --hard HEAD~1
# HEAD~1 上一次提交的 编号(要通过 git log 查看提交日志,也可直接指定提交编号或序号)
git reset --hard cbc3543
# 撤销提交
git revert <commit-id>
# 这条命令会把指定的提交的所有修改回滚,并同时生成一个新的提交。
13. git log(日志)
查看提交日志可以使用 git log 指令,语法格式如下:
代码语言:javascript复制 #查看提交日志
git log [<options>] [<revision range>] [[--] <path>…?]
"git log --graph"
以图形化的方式显示提交历史的关系,这就可以方便地查看提交历史的分支信息,当然是控制台用字符画出来的图形。"git log -1"
则表示显示 1 行。 使用 history 可以查看您在 bash 下输入过的指令。
□ 查看所有分支日志
"git reflog"
中会记录这个仓库中所有的分支的所有更新记录,包括已经撤销的更新。
14. git ls-files(查看文件列表)
使用 git ls-files 指令可以查看指定状态的文件列表,格式如下:
代码语言:javascript复制 #查看指定状态的文件
git ls-files [-z] [-t] [-v] (--[cached|deleted|others|ignored|stage|unmerged|killed|modified])* (-[c|d|o|i|s|u|k|m])*
例子
代码语言:javascript复制 $ git ls-files #默认查看所有缓存(已提交的)的文件
hyy00.txt
hyy02.txt
$ git ls-files -o # 查看未被跟踪的文件
$ git ls-files -s
100644 6adbdc28dfd30b8cd6c32480c4c65c261cc0ff72 0 hyy00.txt
100644 35db16759fb4115448fd06a00b1e076bb527e590 0 hyy02.txt
15.撤销更新
□ 撤销暂存区更新
使用 "git add"
把更新提交到了暂存区。
这时"git status"
的输出中提示我们可以通过 git restore --staged <file>..."
把暂存区的更新移出到 WorkSpace 中。
示例:f6 已经提交,工作区修改,暂存区修改,撤销:
代码语言:javascript复制 $ git add hyy03.txt
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: hyy03.txt
□ 撤销本地仓库更新
使用 git log 查看提交日志
代码语言:javascript复制 $ git log
commit afd439252a9af271c493141fe11065a312413cd8 (HEAD -> master)
Author: 胡宇洋 <2582952862@qq.com>
Date: Sun Nov 28 14:50:41 2021 0800
修改hyy04
commit abc3e822acfde1398855919de04c7e8a66f2de52 (HEAD -> master)
Author: 胡宇洋 <2582952862@qq.com>
Date: Sun Nov 28 14:40:10 2021 0800
hyy04.txt首次提交到本地仓库
commit eaed0f7370433ffe6c49e08ad9a172b9abbeaf2d (HEAD -> master)
Author: 胡宇洋 <2582952862@qq.com>
Date: Sun Nov 28 14:21:28 2021 0800
提交hyy03到本地仓库
commit 0424b988aaaf192c7e2580daf15714c01fb085a0
Author: 胡宇洋 <2582952862@qq.com>
Date: Sun Nov 28 13:56:24 2021 0800
提交hyy002.txt到本地仓库,使用amend修订提交。
commit f2cda2644e0da78e163c4e152e1e86dd4fe1e4f3
Author: 胡宇洋 <2582952862@qq.com>
Date: Sun Nov 28 13:41:42 2021 0800
dddddd指定提交hyy00.txt
撤销提交有两种方式:
使用 HEAD 指针和使用 commit id
在 Git 中,有一个 HEAD 指针指向当前分支中最新的提交。
当前版本,我们使用 "HEAD^",那么再前一个版本可以使用 "HEAD^^",如果想回退到更早的提交,可以使用 "HEADn"。(也就是,HEAD^=HEAD1,HEAD^^=HEAD~2)
代码语言:javascript复制 git reset --hard HEAD^
git reset --hard HEAD~1
git reset --59cf9334cf957535cb328f22a1579b84db0911e5
例子:
代码语言:javascript复制 # 回退前;
$ cat hyy04.txt
123
# 回退到 abc3e(首次提交hyy04.txt)的时候
$ git reset --hard abc3
HEAD is now at abc3e82 hyy04.txt首次提交到本地仓库
# 回退之后查看
$ cat hyy04.txt
dapkiihwoia
现在又想恢复被撤销的提交可用 "git reflog"
查看仓库中所有的分支的所有更新记录,
包括已经撤销的更新,撤销方法与前面一样。
代码语言:javascript复制 $ git reflog
abc3e82 (HEAD -> master) HEAD@{0}: reset: moving to abc3
afd4392 HEAD@{1}: commit: 修改hyy04
abc3e82 (HEAD -> master) HEAD@{2}: commit: hyy04.txt首次提交到本地仓库
eaed0f7 HEAD@{3}: commit: 提交hyy03到本地仓库
# 恢复被撤销的提交(即恢复到撤销前的时候:
# afd4392【commit id】 HEAD@{1}【HEAD指针】: commit: 修改hyy04)
$ git reset --hard HEAD@{1}
HEAD is now at afd4392 修改hyy04
# 或 git reset --hard afd4392
# 恢复后查看
$ cat hyy04.txt
123
--hard:撤销并删除相应的更新 --soft:撤销相应的更新,把这些更新的内容放到 Stage 中
□ reset, restore, revert区别
在日常git工作流中,经常涉及到回退暂存区、回退工作区等撤销操作。 有三个名称相似的命令:git reset
,git restore
和git revert
。
git revert
是进行新的提交,以还原其他提交所做的更改。git revert <commit-id>
这条命令会把指定的提交的所有修改回滚,并同时生成一个新的提交。修改hyy04.txt 内容 echo "123"> hyy04.txt git add hyy04.txt git commit hyy04.txt -m"测试1" git reflog c464f23 (HEAD -> master) HEAD@{0}: commit: 测试1 afd4392 HEAD@{1}: reset: moving to HEAD@{1} abc3e82 HEAD@{2}: reset: moving to abc3 afd4392 HEAD@{3}: commit: 修改hyy04 abc3e82 HEAD@{4}: commit: hyy04.txt首次提交到本地仓库 # 回滚到 afd4392 HEAD@{3}: commit: 修改hyy04 的状态 git revert afd4392 # 然后就会进入到下面的页面(内容不是这次操作的) cat hyy04.txt dapkiihwoia
git restore
使得在工作空间但是不在暂存区的文件撤销更改(内容恢复到没修改之前的状态) $ git add hyy05.txt $ git status On branch master Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: hyy05.txt # 可以看到此时的内容 $ cat hyy05.txt 1 # 修改内容但不add到暂存区 $ echo "12">hyy05.txt $ cat hyy05.txt 12 # restore:使得在工作空间但是不在暂存区的文件撤销更改 $ git restore hyy05.txt $ cat hyy05.txt 1git restore --staged
是将暂存区的文件从暂存区撤出,但不会更改文件的内容。 $ git add hyy05.txt # 将暂存区的文件 hyy05.txt 从暂存区撤出 $ git restore --staged hyy05.txt $ git status On branch master Untracked files: (use "git add <file>..." to include in what will be committed) hyy05.txt nothing added to commit but untracked files present (use "git add" to track)git reset
是关于更新分支,移动顶端(tip)以便从分支中添加或删除提交。 此操作更改提交历史记录。git reset
也可以用来还原索引,与git restore重叠。回退前; $ cat hyy04.txt 123 # 回退到 abc3e(首次提交hyy04.txt)的时候 $ git reset --hard abc3 HEAD is now at abc3e82 hyy04.txt首次提交到本地仓库 # 回退之后查看 $ cat hyy04.txt dapkiihwoia如下所示,我们通过git reset HEAD~1命令回退分支记录:
- Git 把 master 分支移回到 C1;现在我们的本地代码库根本就不知道有 C2 这个提交了。
- 在reset后, C2 所做的变更还在,但是处于未加入暂存区状态(可以通过`git reflog`查看日志文件查看记录,通过commit id|HEAD指针编号,`git reset --hard HEAD@{1}`回到指定状态)。
- `git reset hyy05.txt` 相当于`git add hyy05.txt`的逆操作,如果`hyy05.txt`时新建文件,则不起作用。 git add hyy05.txt git reset hyy05.txt
16. 删除文件
□ 删除未跟踪文件
如果文件还是未跟踪状态,直接删除文件就可了,bash 中使用 rm 可以删除文件,示例如下:
代码语言:javascript复制 $ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
hyy05.txt
nothing added to commit but untracked files present (use "git add" to track)
$ rm hyy05.txt
□ 删除已提交文件
代码语言:javascript复制 $ git ls-files # 查看已提交的文件
hyy00.txt
hyy02.txt
hyy03.txt
hyy04.txt
$ git rm -f hyy00.txt
rm 'hyy00.txt'
-f
:强制删除,物理删除了,同时删除工作区和暂存区中的文件。
撤销删除:
git checkout -- <file>...
# 回到删除前的状态
$ git reset HEAD@{0}
Unstaged changes after reset:
D hyy00.txt
$ git status
On branch master
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: hyy00.txt
# 现在是删除前的状态,
$ git checkout -- hyy00.txt
$ git ls-files
hyy00.txt
hyy02.txt
hyy03.txt
hyy04.txt
□ 删除暂存区的文件,不删除工作区的文件
git rm --cached filename
$ git add hyy.txt
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: hyy.txt
$ git rm --cached hyy.txt
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
hyy.txt
nothing added to commit but untracked files present (use "git add" to track)
△ 文件操作小结
我正在参与2023腾讯技术创作特训营第二期有奖征文,瓜分万元奖池和键盘手表