手把手教你入門Git — Git使用指南(Linux)
系統:ubuntu 18.04 LTS
本文所有git命令操作實驗具有連續性,git小白完全可以從頭到尾跟著本文所有給出的命令走一遍,就會對git有一個初步的了解,應當能做到會用并且大致了解git的版本控制機制,遇到問題的話歡迎留言或私信博主。
git安裝及配置
1 git安裝
sudo apt-get install git
可通過git --version
命令查看,正常輸出git版本號即安裝成功。
2 配置用戶名和郵箱名
git config --global user.name "Your Name"
git config --global user.email "email@example.com"
配置完后可以通過以下命令查看
git config user.name
git config user.email
3 配置SSH公鑰
創建公鑰文件,生成的公鑰文件會保存在本機的~/.ssh目錄下。
ssh-keygen -C 'example@example.com' -t rsa
然后三步詢問直接回車即可(連按三次回車)。
創建完成后進~/.ssh目錄,將公鑰(即id_rsa.pub的內容)復制出來。
cd ~/.ssh
cat id_rsa.pub
如果進入該目錄時提示No such file or directory
,自己手動創建一個即可:mkdir ~/.ssh
。
然后來到瀏覽器端進行操作,首先登錄自己的github賬號(沒有的話自行注冊一個即可),進入到自己的主頁,依次點擊settings->SSH and GPG keys->New SSH Key
,進入到如下頁面:
將剛才保存的id_rsa.pub
文件內容復制到Key
字段,Title
自己起個名字,最好是能代表當前所配置的機器的名字。然后點Add SSH key
,會要求輸入當前github賬號的密碼,按要求輸入就行了。
git本地操作
1 創建倉庫并初始化
倉庫(repository)也叫版本庫,可以看做一個目錄,這個目錄里的所以文件都由Git進行管理,每個文件的修改、刪除,Git都能跟蹤。
-
創建一個目錄
mkdir learnGit
-
將我們新創建的目錄初始化為git可以管理的倉庫:
cd learnGit git init
會輸出
Initialized empty Git repository in /home/ps/JJ_Projects/learnGit/.git/
,表示成功初始化git倉庫。這時會發現該目錄中多出了一個
.git
目錄,這就是git來跟蹤管理版本庫的。
2 添加文件
-
我們首先創建一個README文件,并寫入一些內容:
touch README.txt vim README.txt # 寫入 Learning Git: New File. cat README.txt # 查看文件內容 # 輸出 Learning Git: New File.
-
執行
git add
命令,將文件添加的倉庫。git add README.txt
這條命令不會有輸出,具體作用后文會分析,這里我們先走一遍新建文件的步驟。
-
執行
git commit
命令,將文件提交的倉庫。git commit -m "Submit a new file." # 雙引號內是本次提交的注釋,原則上可以隨便寫,但是盡量能表達出本次提交的改動。
會輸出:
[master (root-commit) 7e21c1f] Submit a new file.1 file changed, 1 insertion(+)create mode 100644 README.txt
表示我們已經成功提交一個新文件。
3 修改文件
我們剛剛已經成功提交了一個新文件到我們的git倉庫,接下來,我們來看一下怎樣修改文件的內容。
-
修改文件內容
vim README.txt # 將其中內容替換為:Learning Git: Modify.
-
查看倉庫狀態
此時,我們可以用
git status
命令來查看一下倉庫當前的狀態: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: README.txtno changes added to commit (use "git add" and/or "git commit -a")
意思很明顯:
README.txt
文件提勁被修改過了,但是現在還沒有改動需要git submit
,因為要先git add
。 -
查看文件改動
用
git diff
查看文件有哪些改動:git diff # 輸出: diff --git a/README.txt b/README.txt index 5107c06..e22e629 100644 --- a/README.txt +++ b/README.txt @@ -1 +1 @@ -Learning Git: New File. +Learning Git: Modify.
即我們剛才進行的修改。
-
向上面一樣,將修改添加到倉庫:
git add README.txt
同樣沒有任何輸出,但是這次我們可以用
git status
來查看一下倉庫當前的狀態:git status # 輸出: On branch master Changes to be committed:(use "git reset HEAD <file>..." to unstage)modified: README.txt
可以看到,已經有一個改動需要被commit了,可以推測add命令應該是將文件的改動放到了某個待提交的臨時位置,后面會具體分析。
-
那下一步就是提交咯:
git commit -m "Modify a file." # 輸出: [master a493237] Modify a file.1 file changed, 1 insertion(+), 1 deletion(-)
文件修改提交成功,我們再查看一下倉庫當前狀態:
git status # 輸出: On branch master nothing to commit, working tree clean
我們剛剛把修改都提交了,所以現在沒有東西要提交。
4 版本回退
使用git進行版本控制,重要的用途之一就是進行版本回退了,我們來看一下怎樣操作。
-
我們先使用
git log
命令來查看一下倉庫的修改日志:git log # 輸出: commit a493237884485d9b0d6c88d64d967293ef5a80b8 (HEAD -> master) Author: user <example@example.com> Date: Wed Aug 18 20:09:27 2021 +0800Modify a file.commit 7e21c1fa1ada0c6b6dce6bef93f0c8e325d716a2 Author: user <example@example.com> Date: Wed Aug 18 19:56:17 2021 +0800Submit a new file.
顯示出我們之前的兩次修改操作。
我們還可以加上
--pretty=online
參數:git log --pretty=oneline # 輸出: a493237884485d9b0d6c88d64d967293ef5a80b8 (HEAD -> master) Modify a file. 7e21c1fa1ada0c6b6dce6bef93f0c8e325d716a2 Submit a new file.
-
我們先查看一下當前README.txt文件中的內容:
cat README.txt # 輸出: Learning Git: Modify. # 是我們上次修改文件后的內容。
使用
git reset
命令,將版本回退:git reset --hard HEAD^ # HEAD表示當前版本,HEAD^表示上一個版本,HEAD^^表示上上版本 輸出: HEAD is now at 7e21c1f Submit a new file.
在查看一下版本回退之后README.txt中的內容:
cat README.txt # 輸出: Learning Git: New File.
可以看到,回退到了我們修改文件之前的內容。
5 git的工作區和暫存區
在繼續介紹git的本地操作之前,我們先來看一下git的版本管理究竟是怎樣進行的。
概念
-
工作區(Working Directory),我們創建的learnGit 目錄就是一個工作區。
-
版本庫,倉庫(Repository),工作區有個隱藏目錄 .git ,這個不算工作區,而是 Git 的版本庫。
-
版本庫里面的 index(stage) 文件叫暫存區,還有Git為我們自動創建的第一個分支 master ,以及指向 master 的一個指針叫做 HEAD。
關系
前面我們提到過,如果我們想把文件添加到Git里面時,需要分兩步:
第一步是用 git add
把文件添加進去,實際上就是把文件修改添加到暫存區。
第二步是用 git commit
提交更改,實際上就是把暫存區的所有內容提交到當前分支。(我們現在只有唯一一個分支 master,所以現在就是往 master 分支上提交更改)
6 管理修改
git做版本控制的關鍵優勢在于:git跟蹤管理的不是文件,而是修改。
我們做這樣一個實驗:
-
首先,在
README.txt
中添加一行vim README.txt # 添加一行 cat README.txt # 輸出: Learning Git: New File. test line 1.
-
將此次修改
add
并查看狀態status
:git add README.txt git status # 輸出: On branch master Changes to be committed:(use "git reset HEAD <file>..." to unstage)modified: README.txtps@rong:~/JJ_Projects/learnGit$
這時我們先不提交,而是再對
README.txt
進行一次修改,按照我們之前的分析,現在我們的第一次修改應該是保存在暫存區。 -
再次修改文件
vim README.txt # 再添加一行 cat README.txt # 輸出: Learning Git: New File. test line 1. test line 2.
-
不對第二次修改進行
add
,直接commit
。現在的應該是第一次修改在暫存區,第二次修改在工作區沒動。git commit -m "test" # 輸出: [master 611366c] test1 file changed, 1 insertion(+)
然后我們查看一下狀態:
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: README.txtno changes added to commit (use "git add" and/or "git commit -a")
我們可以發現,第二次修改并沒有被提交。
因為在工作區的第一次修改被放入暫存區,準備提交;而在工作區的第二次修改并沒有被放入暫存區,所以,
git commit
命令只負責把暫存區的修改提交了。 -
提交后,我們可以用
git diff HEAD -- readme.txt
命令去查看工作區和版本庫里面最新版本的區別:git diff HEAD -- README.txt # 輸出: diff --git a/README.txt b/README.txt index be48ea2..0afce83 100644 --- a/README.txt +++ b/README.txt @@ -1,2 +1,3 @@Learning Git: New File.test line 1. +test line 2.
7 撤銷修改
本地git的撤銷修改操作有三種具體情況,分別是:
(1) 僅修改文件,沒有add
,此時修改僅在工作區。
(2) 修改文件后add
過,但是沒有commit
,此時修改保存在暫存區。
(3) 修改文件后,add
并commit
,此時修改已經提交到倉庫。
接下來我們一個一個看。
-
僅修改文件,沒有
add
,此時修改僅在工作區我們上一個實驗的第二次修改只存在工作區,并未
add
,剛好符合第一種情況,這時的狀態應該是這樣的: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: README.txtno changes added to commit (use "git add" and/or "git commit -a")
其實
status
的輸出信息已經提示到我們了,此時使用checkout
命令即可:git checkout -- README.txt
然后我們查看一下文件內容和狀態信息:
cat README.txt # 輸出: Learning Git: New File. test line 1. git status On branch master nothing to commit, working tree clean
完美撤銷。
-
修改文件后
add
過,但是沒有commit
,此時修改保存在暫存區我們再添加一行測試、
add
,并查看此時狀態:vim README.txt # 添加一行 git add README.txt git status # 輸出: On branch master Changes to be committed:(use "git reset HEAD <file>..." to unstage)modified: README.txt
還是可以從輸出信息看到,可以使用
reset
命令將放到暫存區的修改退回到工作區。git reset HEAD README.txt # 輸出: Unstaged changes after reset: M README.txt 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: README.txtno changes added to commit (use "git add" and/or "git commit -a")
從上面的狀態輸出可以看到,修改已經成功地退回到工作區了。
現在就轉到了情況1,再用
checkout
命令撤銷就可以了。git checkout -- README.txt git status # 輸出: On branch master nothing to commit, working tree clean
-
改文件后,
add
并commit
,此時修改已經提交到倉庫這時已經完車了修改的提交,只能進行版本回退了,上面4已經介紹,這里不再贅述。
8 刪除文件與恢復
-
我們先準備一個待刪除的文件
test.txt
,并add
、commit
到倉庫,這一套大家想必已經熟的不能再熟了,我們直接走一遍。touch test.txt vim test.txt # 添加內容 delete test git add test.txt git commit -m "delete test" # 輸出: [master 08ffedc] delete test1 file changed, 1 insertion(+)create mode 100644 test.txt
-
在工作區中直接刪除
test.py
:rm test.py
這時有兩種情況:
(1) 工作區中誤刪文件,需要恢復
(2) 確實要刪除文件,應該把刪除操作提交到倉庫
-
工作區中誤刪文件,需要恢復
這種情況其實與上面的撤銷修改情況1是一樣的,要將工作區的動作撤銷掉,而這在我們的倉庫中還是存在的,所以還是要請出我們的
checkout
命令就好了。git checkout -- test.txt ls # 輸出: README.txt test.txt
可以看到,我們剛剛在工作區
rm
掉的test.txt
文件已經回來了 -
確實要刪除文件,應該把刪除操作提交到倉庫
我們先把剛剛恢復的
test.txt
再從工作區刪掉。rm test.txt
既然我們確實要刪掉該文件,就直接再用
git rm
刪除:git rm test.py # 輸出: rm 'test.txt'
再將刪除操作提交到倉庫:
git commit -m "delete test" # 輸出: [master 9182ef7] delete test1 file changed, 1 deletion(-)delete mode 100644 test.txt
就大功告成啦。
git遠程操作
注意:遠程倉庫操作需要已經完成SSH公鑰的配置。
新建遠程倉庫并關聯本地倉庫
- 我們先來到網頁端進行操作,登錄github之后,直接點綠色的小new,新建倉庫。
-
網頁端創建完倉庫后回到本地命令行運行如下命令,添加遠程倉庫:
git remote add origin git@github.com:adenialzz/learngit.git
注意改成自己的用戶名,這條命令不會有輸出。添加后,遠程庫的名字就是 origin ,這是Git默認的叫法。
-
然后,我們就可以使用
git push
命令將本地倉庫推到遠程倉庫。git push -u origin master # 輸出: Counting objects: 10, done. Delta compression using up to 20 threads. Compressing objects: 100% (5/5), done. Writing objects: 100% (10/10), 816 bytes | 816.00 KiB/s, done. Total 10 (delta 1), reused 0 (delta 0) remote: Resolving deltas: 100% (1/1), done. remote: This repository moved. Please use the new location: remote: git@github.com:Adenialzz/learnGit.git To github.com:adenialzz/learngit.git* [new branch] master -> master Branch 'master' set up to track remote branch 'master' from 'origin'.
因為遠程庫是空的,所以我們在第一次推送 master 分支時,要加上 -u 參數,Git不但會把本地的
master 分支內容推送的遠程新的 master 分支,還會把本地的
master 分支和遠程的 master 分支關聯起來,在以后的推送或者拉取時就可以簡化命令。這時,我們再到網頁端查看,就可以看到我們的本地倉庫的全部內容已經推倒遠程倉庫(當然,這里只有一個文件,因為我們的
test.txt
已經被刪除掉了)。
將本地倉庫推到遠程
我們新建一個LICENSE.txt
文件,提交到本地倉庫,并推到遠程,這些操作上面到介紹過了,這里簡單過一遍,
touch LICENSE.txt
vim LICENSE.txt # 添加內容
git add LICENSE.txt
git commit -m "add LICENSE"
git push origin master
需要注意的是在第一次關聯過倉庫之后,再推到遠程時,只需git push origin master
,即可把本地 master 分支的最新修改推送至GitHub。現在,我們擁有了真正的分布式版本庫。
將遠程倉庫拉到本地
這個應該是平時沒有深入了解git之前最常用的命令了(^^),將別人的代碼拉到本地。
-
點擊上圖的綠色的Code,將其中內容復制下來
-
在本地使用
clone
命令進行拉取:git clone https://github.com/Adenialzz/learnGit.git
git卸載
先找到git的目錄:通過which git
命令,得到/usr/bin/git
。
然后完全刪除該目錄,并卸載git:
sudo rm -r /usr/bin/git
sudo apt-get remove git
注意要完全卸載git,以上兩步缺一不可。