1. 創(chuàng)建 Git 本地倉庫
要提前說的是,倉庫是進(jìn)行版本控制的一個(gè)文件目錄。我們想對(duì)文件進(jìn)行版本控制,就必須先創(chuàng)建一個(gè)倉庫出來。
創(chuàng)建一個(gè) Git 本地倉庫對(duì)應(yīng)的命令為 git init
,注意命令要在文件目錄下執(zhí)行,例如:
ubuntu@VM-20-5-ubuntu:~/gitcode$ pwd
/home/ubuntu/gitcode
ubuntu@VM-20-5-ubuntu:~/gitcode$ git init
Initialized empty Git repository in /home/ubuntu/gitcode/.git/
ubuntu@VM-20-5-ubuntu:~/gitcode$ ll -a
total 12
drwxrwxr-x 3 ubuntu ubuntu 4096 Apr 16 19:26 ./
drwxr-xr-x 10 ubuntu ubuntu 4096 Apr 16 19:26 ../
drwxrwxr-x 7 ubuntu ubuntu 4096 Apr 16 19:31 .git/
我們發(fā)現(xiàn),當(dāng)前目錄下多了一個(gè) .git
的隱藏文件,.git
目錄是 Git 用來跟蹤管理倉庫的,不要手動(dòng)修改這個(gè)目錄里面的文件,不然改亂了,就把 Git 倉庫給破壞了。
其中包含 Git 倉庫的諸多細(xì)節(jié),使用 tree .git/
命令看看:
ubuntu@VM-20-5-ubuntu:~/gitcode$ tree .git/
.git/
├── branches
├── config
├── description
├── HEAD
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-merge-commit.sample
│ ├── prepare-commit-msg.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ └── update.sample
├── info
│ └── exclude
├── objects
│ ├── info
│ └── pack
└── refs
├── heads
└── tags
9 directories, 16 files
2. 配置 Git
當(dāng)安裝 Git 后首先要做的事情是設(shè)置你的 用戶名稱 和 E-mail 地址,這是非常重要的。配置命令為:
git config [--global] user.name "your name"
git config [--global] user.email "email@example.com"
# 把 your name 改為你的昵稱
# 把 email@example.com 改為你的郵箱
# [--global] 代表 --global 是一個(gè)可選項(xiàng),輸入命令的時(shí)候不要加方框?。?!
其中 --global
是一個(gè)可選項(xiàng)。如果使用了該選項(xiàng),表示這臺(tái)機(jī)器上所有的 Git 倉庫都會(huì)使用這個(gè)配置。如果你希望在不同倉庫中使用不同的 name
或 e-mail
,可以不要 --global
這個(gè)選項(xiàng),但要注意的是,執(zhí)行命令時(shí)必須要在倉庫里。
查看配置的命令為:
git config -l
# 實(shí)機(jī)演示
ubuntu@VM-20-5-ubuntu:~/gitcode$ git config user.name "tjq"
ubuntu@VM-20-5-ubuntu:~/gitcode$ git config user.email "1234567890@qq.com"
ubuntu@VM-20-5-ubuntu:~/gitcode$ git config -l
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
user.name=tjq # 新增
user.email=1234567890@qq.com # 新增
刪除對(duì)應(yīng)配置的命令為:
git config [--global] --unset user.name "your name"
git config [--global] --unset user.email "email@example.com"
# 如果配置的時(shí)候加了 --global 選項(xiàng),那么刪除的時(shí)候也要加
刪除配置后,可以使用查看配置的命令(git config -l
)查看是否真的已經(jīng)刪除。
# 實(shí)機(jī)演示
ubuntu@VM-20-5-ubuntu:~/gitcode$ git config --unset user.name "tjq"
ubuntu@VM-20-5-ubuntu:~/gitcode$ git config --unset user.email "1234567890@qq.com"
ubuntu@VM-20-5-ubuntu:~/gitcode$ git config -l
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
3. 認(rèn)識(shí)工作區(qū)、暫存區(qū)、版本庫
- 工作區(qū):是在電腦上你要寫代碼或文件的目錄。
-
暫存區(qū):英文叫 stage 或 index。一般存放在
.git
目錄下的 index 文件(.git/index
)中,我們有時(shí)把暫存區(qū)也叫做索引(index)。 -
版本庫:又名倉庫,英文名
repository
。工作區(qū)有一個(gè)隱藏目錄.git
,它不算工作區(qū),而是 Git 的版本庫。這個(gè)版本庫里面的所有文件都可以被 Git 管理起來,每個(gè)文件的修改、刪除,Git 都能跟蹤,以便任何時(shí)刻都可以追蹤歷史,或者在將來某個(gè)時(shí)刻可以“還原”。
下圖展示了工作區(qū)、暫存區(qū)和版本庫之間的關(guān)系:
- 圖中左側(cè)為工作區(qū),右側(cè)為版本庫。Git 的版本庫里存了很多東西,其中最重要的就是暫存區(qū)。
- 在創(chuàng)建 Git 版本庫時(shí),Git 會(huì)為我們自動(dòng)創(chuàng)建一個(gè)唯一的 master 分支,以及指向 master 的一個(gè)指針 HEAD。
- 當(dāng)對(duì)工作區(qū)修改(或新增)的文件執(zhí)行
git add
命令時(shí),暫存區(qū)目錄樹的文件索引會(huì)被更新。 - 當(dāng)執(zhí)行提交操作
git commit
時(shí),master 分支會(huì)做相應(yīng)的更新,可以簡單理解為暫存區(qū)的目錄樹才會(huì)被真正寫到版本庫中。
由上述描述中,我們得知:通過新建或粘貼進(jìn)目錄的文件,并不能稱之為向倉庫中新增文件,而只是在工作區(qū)新增了文件。必須要通過使用 git add
和 git commit
命令才能將文件添加到倉庫中進(jìn)行管理!
3.1 添加文件 | 場景一
在包含 .git 的目錄下新建一個(gè) ReadMe 文件,我們可以使用 git add
命令將文件添加到暫存區(qū):
# 添加一個(gè)或多個(gè)文件到暫存區(qū):
git add [file1] [file2] ...
# 添加指定目錄到暫存區(qū),包括子目錄:
git add [dir]
# 添加當(dāng)前目錄下的所有文件改動(dòng)到暫存區(qū):
git add .
再使用 git commit
命令將暫存區(qū)內(nèi)容添加到本地倉庫中:
# 提交暫存區(qū)全部內(nèi)容到本地倉庫中:
git commit -m "message"
# 提交暫存區(qū)的指定文件到倉庫區(qū):
git commit [file1] [file2] ... -m "message"
注意 git commit
后面的 -m
選項(xiàng),要跟上描述本次提交的 message,由用戶自己完成,這部分內(nèi)容絕對(duì)不能省略,并要好好描述,是用來記錄你的提交細(xì)節(jié),是給我們?nèi)丝吹摹?/p>
# 實(shí)機(jī)演示
ubuntu@VM-20-5-ubuntu:~/gitcode$ touch ReadMe
ubuntu@VM-20-5-ubuntu:~/gitcode$ la
.git ReadMe
ubuntu@VM-20-5-ubuntu:~/gitcode$ vim ReadMe
ubuntu@VM-20-5-ubuntu:~/gitcode$ cat ReadMe
hello git
ubuntu@VM-20-5-ubuntu:~/gitcode$ git add ReadMe
ubuntu@VM-20-5-ubuntu:~/gitcode$ git commit -m "add first file"
[master (root-commit) daca7d4] add first file
1 file changed, 1 insertion(+)
create mode 100644 ReadMe
git commit
命令執(zhí)行成功后會(huì)告訴我們,1 個(gè)文件被改動(dòng)(就是我們新添加的 ReadMe 文件),插入了一行內(nèi)容。
我們還可以多次 add 不同的文件,而只 commit 一次便可以提交所有文件,是因?yàn)樾枰峤坏奈募峭ㄍū?add 到暫存區(qū)中,然后一次性 commit 暫存區(qū)的所有修改。
# 實(shí)機(jī)演示
ubuntu@VM-20-5-ubuntu:~/gitcode$ touch file1 file2 file3
ubuntu@VM-20-5-ubuntu:~/gitcode$ la
file1 file2 file3 .git ReadMe
ubuntu@VM-20-5-ubuntu:~/gitcode$ git add file1 file2 file3
ubuntu@VM-20-5-ubuntu:~/gitcode$ git commit -m "add 3 files"
[master 63ffac4] add 3 files
3 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 file1
create mode 100644 file2
create mode 100644 file3
截至目前為止,我們已經(jīng)能夠?qū)⒋a直接提交至本地倉庫了。那么可以查看我們的歷史提交記錄嗎?如何查看?
# 查看歷史提交記錄
git log
# 查看美觀且簡略的歷史提交記錄
git log --pretty=oneline
該命令顯示從最近到最遠(yuǎn)的提交日志,并且可以看到我們 commit 時(shí)的日志消息。
如果嫌輸出信息太多,看得眼花繚亂的,可以試試加上 --pretty=oneline
參數(shù)。
# 實(shí)機(jī)演示
ubuntu@VM-20-5-ubuntu:~/gitcode$ git log
commit 63ffac4330249843d4b68f6a5f59384ba09a0358 (HEAD -> master)
Author: tjq <1234567890@qq.com>
Date: Thu Apr 18 10:46:40 2024 +0800
add 3 files
commit daca7d41906c112f4b11c148a43cd2a0c23a4871
Author: tjq <1234567890@qq.com>
Date: Thu Apr 18 10:20:39 2024 +0800
add first file
# 上面信息太多?試試加上 --pretty=oneline
ubuntu@VM-20-5-ubuntu:~/gitcode$ git log --pretty=oneline
63ffac4330249843d4b68f6a5f59384ba09a0358 (HEAD -> master) add 3 files
daca7d41906c112f4b11c148a43cd2a0c23a4871 add first file
需要說明的是,我們看到的一大串類似 63ffa...a0358
的數(shù)字是每次提交的 commit id
(版本號(hào)),Git 的 commit id
不是 1, 2, 3, … 遞增的數(shù)字,而是一個(gè) SHA1 計(jì)算出來的一個(gè)非常大的數(shù)字,用十六進(jìn)制表示。
3.2 查看 .git 文件
先來看看我們的 .git
目錄結(jié)構(gòu):
ubuntu@VM-20-5-ubuntu:~/gitcode$ tree .git/
.git/
├── branches
├── COMMIT_EDITMSG
├── config
├── description
├── HEAD
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-merge-commit.sample
│ ├── prepare-commit-msg.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ └── heads
│ └── master
├── objects
│ ├── 0e
│ │ └── 6b1780b73cd9220ec5073dc64b42f7ad4bd945
│ ├── 15
│ │ └── a37e9ef171cca4a5d985fccd1fcf9414b2c7cf
│ ├── 63
│ │ └── ffac4330249843d4b68f6a5f59384ba09a0358
│ ├── 8d
│ │ └── 0e41234f24b6da002d962a26c2495ea16a425f
│ ├── da
│ │ └── ca7d41906c112f4b11c148a43cd2a0c23a4871
│ ├── e6
│ │ └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
│ ├── info
│ └── pack
└── refs
├── heads
│ └── master
└── tags
18 directories, 27 files
-
index
就是我們的暫存區(qū),add 后的內(nèi)容都是添加到這里的。 -
HEAD
就是我們默認(rèn)指向 master 分支的指針;ubuntu@VM-20-5-ubuntu:~/gitcode$ cat .git/HEAD ref: refs/heads/master
而默認(rèn)的 master 分支又是什么呢?
ubuntu@VM-20-5-ubuntu:~/gitcode$ cat .git/refs/heads/master 63ffac4330249843d4b68f6a5f59384ba09a0358
打印的
63ffac4330249843d4b68f6a5f59384ba09a0358
是什么東西呢?是不是看起來有點(diǎn)眼熟,其實(shí)保存的就是當(dāng)前最新的commit id
。 -
objects
為 Git 的對(duì)象庫,里面包含了創(chuàng)建的各種版本庫對(duì)象及內(nèi)容。當(dāng)執(zhí)行git add
命令時(shí),暫存區(qū)的目錄樹被更新,同時(shí)工作區(qū)修改(或新增)的文件內(nèi)容被寫入到對(duì)象庫中的一個(gè)新的對(duì)象中,就位于.git/objects
目錄下,讓我們來看看這些對(duì)象有何用處:ubuntu@VM-20-5-ubuntu:~/gitcode$ ls .git/objects/ 0e 15 63 8d da e6 info pack
查找 objects 時(shí)要將
commit id
分成 2 部分,其中前 2 位是文件夾名稱,后 38 位是文件名稱。找到這個(gè)文件之后,一般不能直接看到里面是什么,該類文件是經(jīng)過
sha
(安全哈希算法)加密過的文件,但是我們可以使用git cat-file
命令來查看版本庫對(duì)象的內(nèi)容:git cat-file [選項(xiàng)] [要查看的內(nèi)容]
# 實(shí)機(jī)演示 ubuntu@VM-20-5-ubuntu:~/gitcode$ git cat-file -p 63ffac4330249843d4b68f6a5f59384ba09a0358 tree 15a37e9ef171cca4a5d985fccd1fcf9414b2c7cf parent daca7d41906c112f4b11c148a43cd2a0c23a4871 author tjq <2780888910@qq.com> 1713408400 +0800 committer tjq <2780888910@qq.com> 1713408400 +0800 add 3 files # 這是我們最近一次的提交
其中,還有一行
tree 15a37e9ef171cca4a5d985fccd1fcf9414b2c7cf
,我們使用同樣的方法,看看結(jié)果:ubuntu@VM-20-5-ubuntu:~/gitcode$ git cat-file -p 15a37e9ef171cca4a5d985fccd1fcf9414b2c7cf 100644 blob 8d0e41234f24b6da002d962a26c2495ea16a425f ReadMe 100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 file1 100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 file2 100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 file3
再看 ReadMe 對(duì)應(yīng)的
8d0e41234f24b6da002d962a26c2495ea16a425f
:ubuntu@VM-20-5-ubuntu:~/gitcode$ git cat-file -p 8d0e41234f24b6da002d962a26c2495ea16a425f hello git # 這是我們對(duì) ReadMe 做的修改,被 git 記錄了下來!
總結(jié)一下,在本地的 git 倉庫中,有幾個(gè)文件或者目錄很特殊:
-
index:暫存區(qū),
git add
后會(huì)更新該內(nèi)容。 - HEAD:默認(rèn)指向 master 分支的一個(gè)指針。
-
refs / heads / master:文件里保存當(dāng)前
master
分支的最新commit id
。 - objects:包含了創(chuàng)建的各種版本庫對(duì)象及內(nèi)容,可以簡單理解為放了 git 維護(hù)的所有修改。
在學(xué)習(xí) git 過程中,我們最好能將常見的 git
操作與 .git
目錄當(dāng)中的結(jié)構(gòu)內(nèi)容變化對(duì)應(yīng)起來,這樣有利于我們理解 git 細(xì)節(jié)流程!
3.3 添加文件 | 場景二
學(xué)習(xí)到這里,我們已經(jīng)清楚了如何向倉庫中添加文件,并且對(duì)于工作區(qū)、暫存區(qū)、版本庫也有了一定的認(rèn)識(shí)。那么我們?cè)僬故疽环N添加文件的場景,能加深對(duì)工作區(qū)、暫存區(qū)、版本庫的理解,示例如下:
ubuntu@VM-20-5-ubuntu:~/gitcode$ touch file4 # 1. 新增 file4 文件
ubuntu@VM-20-5-ubuntu:~/gitcode$ git add file4 # 2. 將 file4 添加到暫存區(qū)
ubuntu@VM-20-5-ubuntu:~/gitcode$ touch file5 # 3. 新增 file5 文件
ubuntu@VM-20-5-ubuntu:~/gitcode$ git commit -m "add file" # 4. 提交修改
[master 6856fbd] add file
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 file4
提交后發(fā)現(xiàn)打印了 1 file changed, 0 insertions(+), 0 deletions(-)
,意思是只有一個(gè)文件改變了,這時(shí)我們提出了疑問,不是新增了兩個(gè)文件嗎?
再來回憶下,git add
是將文件添加到暫存區(qū),git commit
是將暫存區(qū)的內(nèi)容添加到本地倉庫中。由于我們并沒有使用 git add file5
,file5 就不在暫存區(qū)中維護(hù),所以我們 commit 的時(shí)候其實(shí)只是把已經(jīng)在暫存區(qū)的 file4 提交了,而遺漏了工作區(qū)的 file5。
4. 修改文件
Git 比其他版本控制系統(tǒng)設(shè)計(jì)的更優(yōu)秀,因?yàn)?Git 跟蹤并管理的是修改,而非文件。
什么是修改?比如你新增了一行,這就是一個(gè)修改;更改了某些字符,是一個(gè)修改;創(chuàng)建一個(gè)新文件,也是一個(gè)修改。
下面我們對(duì) ReadMe 文件進(jìn)行一次修改:
# 實(shí)機(jī)演示
ubuntu@VM-20-5-ubuntu:~/gitcode$ la
file1 file2 file3 file4 file5 .git ReadMe
ubuntu@VM-20-5-ubuntu:~/gitcode$ cat ReadMe
hello git
ubuntu@VM-20-5-ubuntu:~/gitcode$ vim ReadMe
ubuntu@VM-20-5-ubuntu:~/gitcode$ cat ReadMe
hello git
hello world
此時(shí),倉庫中的 ReadMe 和我們工作區(qū)的 ReadMe 是不同的,如何查看當(dāng)前倉庫狀態(tài)呢?
# 查看倉庫狀態(tài)
git status
# 可以用這個(gè)命令查看在上次提交之后,是否對(duì)代碼進(jìn)行了再次修改
# 實(shí)機(jī)演示
ubuntu@VM-20-5-ubuntu:~/gitcode$ git status
On branch master
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: ReadMe
no changes added to commit (use "git add" and/or "git commit -a")
上面的結(jié)果告訴我們,ReadMe 被修改過了,但還沒有完成添加與提交。
目前,我們只知道文件被修改了,如果能知道具體哪些地方被修改了,就更好了,這樣代碼多了以后也可以很方便的進(jìn)行對(duì)比管理。怎么做呢?
# 查看暫存區(qū)和工作區(qū)文件的差異
git diff [file]
# 查看版本庫和工作區(qū)文件的差異
git diff HEAD -- [file]
# git diff [file] 實(shí)機(jī)演示
ubuntu@VM-20-5-ubuntu:~/gitcode$ git diff ReadMe
diff --git a/ReadMe b/ReadMe
index 8d0e412..05fe86c 100644
--- a/ReadMe
+++ b/ReadMe
@@ -1 +1,2 @@
hello git
+hello world
# git diff HEAD -- [file] 實(shí)機(jī)演示
ubuntu@VM-20-5-ubuntu:~/gitcode$ git diff HEAD -- ReadMe
diff --git a/ReadMe b/ReadMe
index 8d0e412..05fe86c 100644
--- a/ReadMe
+++ b/ReadMe
@@ -1 +1,2 @@
hello git
+hello world
git diff [file]
命令用來顯示暫存區(qū)和工作區(qū)文件的差異,顯示的格式正是 Unix 通用的 diff 格式。也可以使用 git diff HEAD -- [file]
命令來查看版本庫和工作區(qū)文件的區(qū)別。
知道了對(duì) ReadMe 做了什么修改后,再把它提交到本地倉庫就放心多了。
# git add 后再次查看倉庫狀態(tài)
ubuntu@VM-20-5-ubuntu:~/gitcode$ git add ReadMe
ubuntu@VM-20-5-ubuntu:~/gitcode$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: ReadMe
git add
之后,就沒有看到上面 no changes added to commit (use "git add" and/or "git commit -a")
的消息了。接下來我們繼續(xù) git commit
即可:
# git commit 后再次查看倉庫狀態(tài)
ubuntu@VM-20-5-ubuntu:~/gitcode$ git commit -m "modify ReadMe file"
[master 1c25401] modify ReadMe file
1 file changed, 1 insertion(+)
ubuntu@VM-20-5-ubuntu:~/gitcode$ git status
On branch master
nothing to commit, working tree clean # 倉庫狀態(tài)恢復(fù)正常
5. 版本回退
之前我們提到過,Git 能夠管理文件的歷史版本,這也是版本控制器重要的能力。如果有一天你發(fā)現(xiàn)之前做的工作出現(xiàn)了很大的問題,需要在某個(gè)特定的歷史版本重新開始,這個(gè)時(shí)候,就需要版本回退的功能了。
# 版本回退
git reset [--soft | --mixed | --hard] [HEAD]
執(zhí)行 git reset
命令用于版本回退,可以指定退回某一次提交的版本。要解釋一下“回退”本質(zhì)是要將版本庫中的內(nèi)容進(jìn)行回退,工作區(qū)或暫存區(qū)是否回退由命令參數(shù)決定:
選項(xiàng) | 工作區(qū) | 暫存區(qū) | 版本庫 |
---|---|---|---|
–soft | 不回退 | 不回退 | 回退 |
–mixed(默認(rèn)) | 不回退 | 回退 | 回退 |
–hard(慎用) | 回退 | 回退 | 回退 |
-
--soft
參數(shù)對(duì)于工作區(qū)和暫存區(qū)的內(nèi)容都不變,只是將版本庫回退到某個(gè)指定版本。 -
--mixed
為默認(rèn)選項(xiàng),使用時(shí)可以不用帶該參數(shù)。該參數(shù)將暫存區(qū)的內(nèi)容退回為指定提交版本內(nèi)容,工作區(qū)文件保持不變。 -
--hard
參數(shù)將暫存區(qū)與工作區(qū)都退回到指定版本。切記工作區(qū)有未提交的代碼時(shí)不要用這個(gè)命令,因?yàn)楣ぷ鲄^(qū)會(huì)回滾,你沒有提交的代碼就再也找不回了,所以使用該參數(shù)一定要慎重。 -
HEAD
說明:- 可直接寫成 commit id,表示指定退回的版本
- 可以使用 ^ 表示:
- HEAD 表示當(dāng)前版本
- HEAD^ 表示上一個(gè)版本
- HEAD^^ 表示上上個(gè)版本
- …
- 也可以使用 ~數(shù)字 表示:
- HEAD~0 表示當(dāng)前版本
- HEAD~1 表示上一個(gè)版本
- HEAD~2 表示上上個(gè)版本
- …
為了便于表述,方便測(cè)試回退功能,我們先做一些準(zhǔn)備工作:更新 3 個(gè)版本的 ReadMe,并分別進(jìn)行 3 次提交,如下所示:
# 第一次修改提交
ubuntu@VM-20-5-ubuntu:~/gitcode$ cat ReadMe
hello git
hello world
hello version1 # 第1次新增
ubuntu@VM-20-5-ubuntu:~/gitcode$ git add ReadMe
ubuntu@VM-20-5-ubuntu:~/gitcode$ git commit -m "add version1"
[master 1fbbbb8] add version1
1 file changed, 1 insertion(+)
# 第二次修改提交
ubuntu@VM-20-5-ubuntu:~/gitcode$ cat ReadMe
hello git
hello world
hello version1 # 第1次新增
hello version2 # 第2次新增
ubuntu@VM-20-5-ubuntu:~/gitcode$ git add ReadMe
ubuntu@VM-20-5-ubuntu:~/gitcode$ git commit -m "add version2"
[master 792517a] add version2
1 file changed, 1 insertion(+)
# 第三次修改提交
ubuntu@VM-20-5-ubuntu:~/gitcode$ cat ReadMe
hello git
hello world
hello version1 # 第1次新增
hello version2 # 第2次新增
hello version3 # 第3次新增
ubuntu@VM-20-5-ubuntu:~/gitcode$ git add ReadMe
ubuntu@VM-20-5-ubuntu:~/gitcode$ git commit -m "add version3"
[master ca0330f] add version3
1 file changed, 1 insertion(+)
# 查看歷史提交記錄
ubuntu@VM-20-5-ubuntu:~/gitcode$ git log --pretty=oneline
ca0330f09ba66638fc757525042034d82bb7ee90 (HEAD -> master) add version3
792517a8bc024eab200301baf8691de821548cbe add version2
1fbbbb826ccc07c0037f7208faeefeb577195f8c add version1
...
現(xiàn)在,如果我們?cè)谔峤煌?version 3 后,發(fā)現(xiàn) version 3 編寫錯(cuò)誤,想回退到 version 2,重新基于 version 2 開始編寫。
由于我們?cè)谶@里希望的是將工作區(qū)的內(nèi)容也回退到 version 2
版本,所以需要用到 --hard
參數(shù),示例如下:
# 查看歷史提交記錄
ubuntu@VM-20-5-ubuntu:~/gitcode$ git log --pretty=oneline
ca0330f09ba66638fc757525042034d82bb7ee90 (HEAD -> master) add version3
792517a8bc024eab200301baf8691de821548cbe add version2
1fbbbb826ccc07c0037f7208faeefeb577195f8c add version1
...
# 輸入 commit id 指定回退到 version2
ubuntu@VM-20-5-ubuntu:~/gitcode$ git reset --hard 792517a8bc024eab200301baf8691de821548cbe
HEAD is now at 792517a add version2
ubuntu@VM-20-5-ubuntu:~/gitcode$ cat ReadMe
hello git
hello world
hello version1
hello version2
我們發(fā)現(xiàn):此時(shí) ReadMe 文件的內(nèi)容,已經(jīng)回退到 version 2 了!當(dāng)前我們?cè)俅斡?git log
查看一下提交日志,發(fā)現(xiàn) HEAD
指向了 version2,如下所示:
ubuntu@VM-20-5-ubuntu:~/gitcode$ git log --pretty=oneline
792517a8bc024eab200301baf8691de821548cbe (HEAD -> master) add version2
1fbbbb826ccc07c0037f7208faeefeb577195f8c add version1
...
到這里一般的回退功能就演示完了,但是現(xiàn)在我后悔了,想再回到 version 3 怎么辦?我們可以繼續(xù)使用 git reset
命令,回退到 version 3
版本,但我們必須要拿到 version 3
的 commit id
才能指定回退的版本。
但我們看到了 git log
并不能打印出 version 3
的 commit id
,我們?cè)撊绾握一啬兀?/p>
# 顯示本地每次提交的信息
git reflog
# 實(shí)機(jī)演示
ubuntu@VM-20-5-ubuntu:~/gitcode$ git reflog
792517a (HEAD -> master) HEAD@{0}: reset: moving to 792517a8bc024eab200301baf8691de821548cbe
ca0330f HEAD@{1}: commit: add version3 # version 3 的記錄
792517a (HEAD -> master) HEAD@{2}: commit: add version2
1fbbbb8 HEAD@{3}: commit: add version1
1c25401 HEAD@{4}: commit: modify ReadMe file
e094860 HEAD@{5}: commit: add file5
6856fbd HEAD@{6}: commit: add file
63ffac4 HEAD@{7}: commit: add 3 files
daca7d4 HEAD@{8}: commit (initial): add first file
這樣,你就可以很方便的找到你的所有操作記錄了,但 ca0330f
這個(gè)是啥東西?其實(shí)這就是 version 3
的 commit id
的一部分。
沒錯(cuò),Git 版本回退的時(shí)候,也可以使用部分 commit id 來代表目標(biāo)版本。示例如下:
# 回退到 version 3
ubuntu@VM-20-5-ubuntu:~/gitcode$ git reset --hard ca0330f
HEAD is now at ca0330f add version3
# 查看工作區(qū)
ubuntu@VM-20-5-ubuntu:~/gitcode$ cat ReadMe
hello git
hello world
hello version1
hello version2
hello version3
# 查看 log
ubuntu@VM-20-5-ubuntu:~/gitcode$ git log --pretty=oneline
ca0330f09ba66638fc757525042034d82bb7ee90 (HEAD -> master) add version3
792517a8bc024eab200301baf8691de821548cbe add version2
1fbbbb826ccc07c0037f7208faeefeb577195f8c add version1
1c25401534e7b402fc77529a1014647d2268447e modify ReadMe file
e094860cb7f95c34041e3520d17ee393965740c1 add file5
6856fbd20a828ed8c32b4f03982c8b1947c8b465 add file
63ffac4330249843d4b68f6a5f59384ba09a0358 add 3 files
daca7d41906c112f4b11c148a43cd2a0c23a4871 add first file
在長時(shí)間開發(fā)中,提交次數(shù)過多 / 本地信息丟失,可能使用 git reflog
也無法找到想要的 commit id
了,所以我們?cè)诎姹净赝藭r(shí)一定要慎重,后悔藥也不是萬能的!
值得一提的是:Git 的版本回退速度非???,因?yàn)?Git 在內(nèi)部有個(gè)指向當(dāng)前分支(此處是 master)的 HEAD 指針,refs/heads/master
文件里保存當(dāng)前 master
分支的最新 commit id
。當(dāng)我們回退版本的時(shí)候,Git 僅僅是給 refs/heads/master
中存儲(chǔ)一個(gè)特定的 version,可以簡單理解成如下示意圖:
6. 撤銷修改
如果我們?cè)诠ぷ鲄^(qū)寫了很長時(shí)間代碼,越寫越難受,感覺自己寫的代碼太垃圾了,想恢復(fù)到上一個(gè)版本,如何操作?
6.1 情況一:對(duì)于工作區(qū)的代碼,還沒有 add
你當(dāng)然可以直接手動(dòng)刪除代碼,這個(gè)誰都會(huì),但是在代碼量很多的情況下,這種方法還適用嗎?
Git 其實(shí)為我們提供了更好的方式:
# 對(duì)工作區(qū)代碼撤銷
git checkout -- [file]
我們可以使用這個(gè)命令讓工作區(qū)的文件回到最近一次 add
或 commit
時(shí)的狀態(tài)。要注意 git checkout -- [file]
命令中的 --
很重要,切記不要省略,一旦省略,該命令就變?yōu)槠渌馑剂?/strong>。
# 實(shí)機(jī)演示
# 向 ReadMe 中新增一行代碼
ubuntu@VM-20-5-ubuntu:~/gitcode$ vim ReadMe
ubuntu@VM-20-5-ubuntu:~/gitcode$ cat ReadMe
hello git
hello world
hello version1
hello version2
hello version3
This piece of code is like shit # 新增
# 恢復(fù)到上一次 add 或 commit
ubuntu@VM-20-5-ubuntu:~/gitcode$ git checkout -- ReadMe
ubuntu@VM-20-5-ubuntu:~/gitcode$ cat ReadMe
hello git
hello world
hello version1
hello version2
hello version3
6.2 情況二:已經(jīng) add,但沒有 commit
add 后,代碼保存到了暫存區(qū),如何撤銷?
# 向 ReadMe 中新增一行代碼
ubuntu@VM-20-5-ubuntu:~/gitcode$ vim ReadMe
ubuntu@VM-20-5-ubuntu:~/gitcode$ cat ReadMe
hello git
hello world
hello version1
hello version2
hello version3
This piece of code is like shit # 新增
# add 存入暫存區(qū)
ubuntu@VM-20-5-ubuntu:~/gitcode$ git add ReadMe
ubuntu@VM-20-5-ubuntu:~/gitcode$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: ReadMe
回憶一下上面學(xué)過的 git reset
回退命令,該命令如果使用 --mixed
參數(shù),可以將暫存區(qū)的內(nèi)容退回為指定的版本內(nèi)容,但工作區(qū)文件保持不變。我們可以用這個(gè)命令回退暫存區(qū)的內(nèi)容:
# --mixed 是默認(rèn)參數(shù),使用時(shí)可以省略
ubuntu@VM-20-5-ubuntu:~/gitcode$ git reset HEAD ReadMe
Unstaged changes after reset:
M ReadMe
# 使用 git status 查看狀態(tài),發(fā)現(xiàn)暫存區(qū)是干凈的,工作區(qū)有修改
ubuntu@VM-20-5-ubuntu:~/gitcode$ git status
On branch master
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: ReadMe
no changes added to commit (use "git add" and/or "git commit -a")
現(xiàn)在可以使用剛才 情況一 中的 git checkout -- [file]
撤銷命令,把工作區(qū)的內(nèi)容撤銷:
ubuntu@VM-20-5-ubuntu:~/gitcode$ git checkout -- ReadMe
ubuntu@VM-20-5-ubuntu:~/gitcode$ git status
On branch master
nothing to commit, working tree clean # 工作區(qū)是干凈的
ubuntu@VM-20-5-ubuntu:~/gitcode$ cat ReadMe
hello git
hello world
hello version1
hello version2
hello version3 # 新增的代碼沒有了
6.3 情況三:已經(jīng) add 了,并且也 commit 了
不要擔(dān)心,我們可以使用 git reset --hard HEAD^
命令回退到上一個(gè)版本!
不過,這是有條件的,即:我們還沒有把本地倉庫的代碼推送到遠(yuǎn)程倉庫(gitee / github),因?yàn)槌蜂N功能本質(zhì)就是為了防止不好的代碼被推送到遠(yuǎn)端。
# 實(shí)機(jī)演示
# 向 ReadMe 中新增一行代碼
ubuntu@VM-20-5-ubuntu:~/gitcode$ vim ReadMe
ubuntu@VM-20-5-ubuntu:~/gitcode$ cat ReadMe
hello git
hello world
hello version1
hello version2
hello version3
This piece of code is like shit # 新增
# 提交
ubuntu@VM-20-5-ubuntu:~/gitcode$ git add ReadMe
ubuntu@VM-20-5-ubuntu:~/gitcode$ git commit -m "test quash"
[master 15e3520] test quash
1 file changed, 1 insertion(+)
# 回退
ubuntu@VM-20-5-ubuntu:~/gitcode$ git reset --hard HEAD^
HEAD is now at ca0330f add version3
ubuntu@VM-20-5-ubuntu:~/gitcode$ cat ReadMe
hello git
hello world
hello version1
hello version2
hello version3
總結(jié):
工作區(qū) | 暫存區(qū) | 版本庫 | 解決方法 |
---|---|---|---|
最新版本 | 空 | 上一版本 | 其他版本 |
git check -- [file] 撤銷工作區(qū)到上一版本 |
最新版本 | 最新版本 | 上一版本 | 其他版本 |
git reset [--mixed | --hard] [HEAD] 回退暫存區(qū)和工作區(qū) |
最新版本 | 最新版本 | 最新版本 | 上一版本 | 其他版本 |
git reset [--hard] [HEAD] 回退版本庫、暫存區(qū)和工作區(qū) |
7. 刪除文件
在 Git 中,刪除一個(gè)文件不僅僅是把工作區(qū)的文件刪除,還要把版本庫中對(duì)應(yīng)的文件也刪除,否則會(huì)造成工作區(qū)與版本庫不匹配的問題!
我們刪除之前提交的 file5 試試:
# 實(shí)機(jī)演示
# rm 刪除工作區(qū)的 file5
ubuntu@VM-20-5-ubuntu:~/gitcode$ ls
file1 file2 file3 file4 file5 ReadMe
ubuntu@VM-20-5-ubuntu:~/gitcode$ rm file5
# 查看狀態(tài)
ubuntu@VM-20-5-ubuntu:~/gitcode$ 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: file5
no changes added to commit (use "git add" and/or "git commit -a")
# git status 提示我們工作區(qū)被修改了(刪除也算修改)
# 我們需要把本次修改提交到版本庫
# 提交
ubuntu@VM-20-5-ubuntu:~/gitcode$ git add file5
ubuntu@VM-20-5-ubuntu:~/gitcode$ git commit -m "delete file5"
[master 6fdee7a] delete file5
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 file5
# 再次查看
ubuntu@VM-20-5-ubuntu:~/gitcode$ git status
On branch master
nothing to commit, working tree clean
ubuntu@VM-20-5-ubuntu:~/gitcode$ ls
file1 file2 file3 file4 ReadMe
# 到這里才算是刪干凈了
除了上面的基本方法以外,Git 還提供了一個(gè)專用的刪除命令:
# 刪除文件
git rm [file]
使用此命令可以讓我們少 add
一次,相當(dāng)于直接把工作區(qū)的刪除操作同步到了暫存區(qū),我們刪除 file4 試試:
ubuntu@VM-20-5-ubuntu:~/gitcode$ ls
file1 file2 file3 file4 ReadMe
# 使用 git rm 命令刪除 file4
ubuntu@VM-20-5-ubuntu:~/gitcode$ git rm file4
rm 'file4'
ubuntu@VM-20-5-ubuntu:~/gitcode$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: file4
ubuntu@VM-20-5-ubuntu:~/gitcode$ git commit -m "delete file4"
[master 0c91580] delete file4
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 file4
# 刪除完成后查看
ubuntu@VM-20-5-ubuntu:~/gitcode$ git status
On branch master
nothing to commit, working tree clean
ubuntu@VM-20-5-ubuntu:~/gitcode$ ls
file1 file2 file3 ReadMe
現(xiàn)在,我們就掌握了兩種在 Git 中刪除文件的方式。文章來源:http://www.zghlxwxcb.cn/news/detail-855624.html
8. 本文命令總結(jié)
為了方便查閱,我按照本文的先后順序,在這里列出我們學(xué)習(xí)到的 Git 新命令:文章來源地址http://www.zghlxwxcb.cn/news/detail-855624.html
1. 創(chuàng)建本地倉庫
git init
2. 配置 git
git config [--global] user.name "your name"
git config [--global] user.email "email@example.com"
3. 查看配置
git config -l
4. 刪除配置
git config [--global] --unset user.name "your name"
git config [--global] --unset user.email "email@example.com"
5. 添加文件
# 添加一個(gè)或多個(gè)文件到暫存區(qū):
git add [file1] [file2] ...
# 添加指定目錄到暫存區(qū),包括子目錄:
git add [dir]
# 添加當(dāng)前目錄下的所有文件改動(dòng)到暫存區(qū):
git add .
6. 提交文件
# 提交暫存區(qū)全部內(nèi)容到本地倉庫中:
git commit -m "message"
# 提交暫存區(qū)的指定文件到倉庫區(qū):
git commit [file1] [file2] ... -m "message"
7. 查看提交記錄
# 查看歷史提交記錄
git log
# 查看美觀且簡略的歷史提交記錄
git log --pretty=oneline
8. 查看版本庫對(duì)象的內(nèi)容
git cat-file [選項(xiàng)] [要查看的內(nèi)容]
9. 查看倉庫狀態(tài)
git status
10. 查看文件間差異
# 查看暫存區(qū)和工作區(qū)文件的差異
git diff [file]
# 查看版本庫和工作區(qū)文件的差異
git diff HEAD -- [file]
11. 版本回退
git reset [--soft | --mixed | --hard] [HEAD]
12. 顯示本地每次提交的信息
git reflog
13. 撤銷工作區(qū)操作回上個(gè)版本
git checkout -- [file]
14. 刪除文件
git rm [file]
到了這里,關(guān)于【Git】從零開始的 Git 基本操作的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!