目录
工作区、暂存库、版本库
工作区:在电脑上写代码或文件的目录
暂存区:存放在.git目录下的index文件
版本库:隐藏目录.git文件,版本库里的所有文件都可以被Git管理起来,每个文件的修改、删除Git都能跟踪,以便任何时刻都可以追踪历史,或者在某个时刻可以"还原"
图中左侧为⼯作区,右侧为版本库。Git 的版本库⾥存了很多东西,其中最重要的就是暂存区。在创建 Git 版本库时,Git 会为我们⾃动创建⼀个唯⼀的 master 分⽀,以及指向 master 的⼀个指针叫 HEAD。当对⼯作区修改(或新增)的⽂件执⾏ git add 命令时,暂存区⽬录树的⽂件索引会被更新。 当执⾏提交操作 git commit 时,master 分⽀会做相应的更新,可以简单理解为暂存区的⽬录树才会被真正写到版本库中。
查看.git文件
当执行文件的git add操作后,会在.git/objects/中存储blob对象存储文件内容(blob对象本身只包含文件的内容,不包含文件名或任何其他元数据)并在.git/index/存储对应的二进制文件,当执行git commit操作后,会将暂存区中的文件commit进master中。,同时commit id和tree会存储进.git/object/中
cpp
.git/
|-- branches
|-- config
|-- description
|-- HEAD
|-- hooks
| |-- applypatch-msg.sample
| |-- commit-msg.sample
| |-- post-update.sample
| |-- pre-applypatch.sample
| |-- pre-commit.sample
| |-- prepare-commit-msg.sample
| |-- pre-push.sample
| |-- pre-rebase.sample
| `-- update.sample
|-- info
| `-- exclude
|-- objects
| |-- info
| `-- pack
`-- refs
|-- heads
`-- tags
HEAD是默认指向master分支的指针
cpp
[paper@VM-16-16-centos ~]$ cat .git/HEAD
ref: refs/heads/master
而master指向commit id,是执行提交对象的标识符,使用git cat-file -p [commit id]可以查看commit id中存储的内容,包括tree、parent(commit id)、author、committer
cpp
[paper@VM-16-16-centos ~]$ cat .git/refs/heads/master
886c3d8a8e78088374d4ecfdcceaf91467f49571
[paper@VM-16-16-centos ~]$ git cat-file -p
886c3d8a8e78088374d4ecfdcceaf91467f49571
tree cf987c72c4a93e8a2d35d2aab4a4b1085011006f
parent f21b3cfa4aa4d2a1bea886feb4864cc8905b815d
parent 93bc771fc95e137549ba4b58b9b597b3d46256c3
author yuan-peiqi <paper13240347791@163.com> 1725344145 +0800
committer yuan-peiqi <paper13240347791@163.com> 1725344145 +0800
file1
在tree内可查看提交线上的blob对象
cpp
[paper@VM-16-16-centos ~]$ git cat-file -p
cf987c72c4a93e8a2d35d2aab4a4b1085011006f
100644 blob 7a8b68e7de2ee6ef4d404ff8c7d65a083c084d07 file1
在blob内可查看文件内写入的信息
cpp
[paper@VM-16-16-centos ~]$ git cat-file -p
7a8b68e7de2ee6ef4d404ff8c7d65a083c084d07
hello git
hello world
write aaa for new branch
修改文件
当执行commit命令之后,暂存区的内容被提交了,暂存区的文件依然存在,当更改工作区后,工作区的内容不会自动更新至暂存区,需要手动的git add才能实现将修改添加至暂存区,使用git status指令就可以查看修改后的文件是否完成添加和提交。
cpp
[paper@VM-16-16-centos ~]$ git status
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: file1
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# .bash_history
# .bash_logout
# .bash_profile
# .bashrc
# .cache/
# .gitconfig
# .viminfo
# file
no changes added to commit (use "git add" and/or "git commit -a")
但git status指令只能查看状态,不能确切显示哪里改动了,使用git diff [file]和git diff HEAD [file]可以查看哪里出现改动,其中git diff [file]可以查看暂存区和工作区的差异,git diff HEAD [file]可以查看版本库和工作区的差异
cpp
[paper@VM-16-16-centos ~]$ git diff file1
diff --git a/file1 b/file1
index 7a8b68e..0d99f10 100644
--- a/file1
+++ b/file1
@@ -1,3 +1,4 @@
hello git
hello world
write aaa for new branch
+wirte bbb for new branch
[paper@VM-16-16-centos ~]$ git diff HEAD file1
diff --git a/file1 b/file1
index 7a8b68e..0d99f10 100644
--- a/file1
+++ b/file1
@@ -1,3 +1,4 @@
hello git
hello world
write aaa for new branch
+wirte bbb for new branch
版本回退
执⾏ git reset 命令⽤于回退版本,可以指定退回某⼀次提交的版本。要解释⼀下"回退"本质是要将版本库中的内容进⾏回退,⼯作区或暂存区是否回退由命令参数决定:
git reset 命令语法格式为: git reset [-- soft | -- mixed | -- hard ] [ HEAD ]
- --mixed 为默认选项,使⽤时可以不⽤带该参数。该参数将暂存区的内容退回为指定提交版本内容,⼯作区⽂件保持不变。
- --soft 参数对于⼯作区和暂存区的内容都不变,只是将版本库回退到某个指定版本。
- --hard 参数将暂存区与⼯作区都退回到指定版本。切记⼯作区有未提交的代码时不要⽤这个命令,因为⼯作区会回滚,你没有提交的代码就再也找不回了,所以使⽤该参数前⼀定要慎重。
HEAD 说明:
- 可直接写成 commit id,表⽰指定退回的版本
- HEAD 表⽰当前版本
- HEAD^ 上⼀个版本
- HEAD^^ 上上⼀个版本
撤销修改
工作区的代码还没有add:
直接在文件中删除,或者使用git checkout --[file]指令
cpp
[paper@VM-16-16-centos ~]$ vim file1
[paper@VM-16-16-centos ~]$ cat file1
hello git
hello world
write aaa for new branch
11111:
[paper@VM-16-16-centos ~]$ git checkout -- file1
[paper@VM-16-16-centos ~]$ cat file1
hello git
hello world
write aaa for new branch
已经add,但没有commit:
此时在工作区和暂存区修改了,对于工作区可以使用上述方法撤销修改,对于暂存区可以使用git reset --mixed指令修改
cpp
[paper@VM-16-16-centos ~]$ git add file1
[paper@VM-16-16-centos ~]$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: file1
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# .bash_history
# .bash_logout
# .bash_profile
# .bashrc
# .cache/
# .file1.swp
# .gitconfig
# .viminfo
# file
[paper@VM-16-16-centos ~]$ git reset HEAD file1
Unstaged changes after reset:
M file1
[paper@VM-16-16-centos ~]$ git status
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: file1
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# .bash_history
# .bash_logout
# .bash_profile
# .bashrc
# .cache/
# .file1.swp
# .gitconfig
# .viminfo
# file
no changes added to commit (use "git add" and/or "git commit -a")
[paper@VM-16-16-centos ~]$ git checkout -- file1
[paper@VM-16-16-centos ~]$ git status
# On branch master
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# .bash_history
# .bash_logout
# .bash_profile
# .bashrc
# .cache/
# .file1.swp
# .gitconfig
# .viminfo
# file
nothing added to commit but untracked files present (use "git add" to track)
已经add,并且也commit了:
可以直接使用git reset --hard HEAD^回退到上一个版本
cpp
[paper@VM-16-16-centos ~]$ vim file1
[paper@VM-16-16-centos ~]$ git add file1
[paper@VM-16-16-centos ~]$ git commit -m "file1"
[master 9348ccd] file1
1 file changed, 1 insertion(+)
[paper@VM-16-16-centos ~]$ git reset --hard HEAD^
HEAD is now at 886c3d8 file1
[paper@VM-16-16-centos ~]$ git status
# On branch master
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# .bash_history
# .bash_logout
# .bash_profile
# .bashrc
# .cache/
# .file1.swp
# .gitconfig
# .viminfo
# file
nothing added to commit but untracked files present (use "git add" to track)
删除文件
删除文件不仅要删除工作区的文件还需要删除暂存区和版本库中的文件,用三部指令分别执行操作
cpp
rm -rf file1
git rm file1
git commmit -m "delete file1"