Git基礎實用指南

做好版本控制,保存清晰的修改歷史,利於項目管理,有效對抗混亂。

一 Git介紹

Git是一個分佈式版本控制系統工具。

一開始Linux是可以免費使用付費的BitMover旗下的BitKeeper版本控制系統的,但是因爲Samba的開發者Andrew Tridgell嘗試破解BitKeeper協議,導致BitMover收回了BitKeeper的免費使用權。所以Linus大概花了10天用c寫了一個版本控制系統,並開始用它提交Linux核心代碼,這就是Git。

1 分佈式和集中式的區別

集中式版本控制系統依賴於中心服務器,版本庫保存在服務器上,需要修改的時候,先從服務器獲取最新的版本,修改完成後再推給服務器,必須要在有網的情況下才能使用。

分佈式版本控制系統則沒有必要的中心服務器,每個人的電腦上都有完整的版本庫,提交代碼無需服務器參與;兩個人對相同文件做的不同修改,也可以直接推送給對方。分佈式版本控制系統中的服務器,更多的工作是保存所有人的改動,方便大家同步。

所以分佈式和集中式最主要的區別是:是否能夠在各自的電腦上獨立操作而無需服務器參與。

2 Gitlab、Github、Gerrit的區別

Git:一個版本控制工具。
Github:一個只支持通過Git進行版本控制的在線代碼倉庫託管平臺。
Gitlab:一個使用Git進行代碼版本控制的倉庫管理系統軟件。和Github不同之處在於通過Gitlab可以自己搭建一個Git的私有服務器,並且有完備的web前端進行管理和權限控制。類似於可以自己搭建一個私有的Github。
Gerrit:一個開源的代碼審查軟件,主要優化代碼提交後,從開始review到合併前的多次代碼提交的流程。

二 Git整體框架

1 Git的三個工作區域

本地工作區域需要了解的概念:

  1. 工作目錄:就是我們看到的目錄
  2. 暫存區(Index/Stage):.git/index,存放commit要提交的內容
  3. Git倉庫:.git目錄,記錄所有的提交

常用命令和Git工作區域之間的關係:

三 Git基本操作

1 Git配置

Git作爲一個工具,自然就有一些配置,配置通過git config命令進行。
比如,Git必須要設置的配置user.nameuser.email,命令爲:

git config --global user.name Farmer
git config --global user.email [email protected]

Git的配置包括全局配置和倉庫級別的配置,如果沒有指定--global,則必須在Git倉庫內執行,表示對當前倉庫進行配置。
user.nameuser.email相當於配置的key,後面的參數就是value,如果命令中只指定key,則表示讀取當前配置中該key的值。

爲了提高效率,推薦使用git config --global alias.xx xxxx爲常用的命令設置別稱。如下:

git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.st status
git config --global alias.br branch
git config --global alias.hist 'log --pretty=format:"%h %ad | %s%d [%an]" --graph --date=short'

通常還會通過下面的命令修改Git默認使用的編輯器(比如修改爲vim):

git config --global core.editor vim

全局配置保存在用戶目錄~/.gitconfig,倉庫級別配置保存在倉庫目錄.git/config

2 Git倉庫創建

通過git init即可初始化一個空的倉庫,此時沒有任何文件添加了版本控制。
或者也可以通過git clone克隆一個現有的倉庫,然後在其基礎上修改。

當然也是可以清空克隆來的倉庫的所有提交記錄的。

3 查看倉庫狀態

使用命令git status查看當前倉庫狀態。
任何時候(合併代碼遇到衝突的過程中、執行rebase命令的過程中)都可以通過此命令確定倉庫的狀態,並且在不同狀態下,按照當前狀態可以執行的操作有一系列的命令提示。

如下圖,在執行合併代碼的過程中,存在的一些命令提示:

在合併代碼時,可能會遇到衝突,此時git status會提示我們要手動解決衝突,然後再執行後續操作,或者終止合併。

4 分支操作

一般來說,在工作中存在協同辦公,大家在各自的分支上進行改動,最後合併在master分支上。
常用的命令如下:

操作 命令
創建分支 git branch <name>
查看分支 git branch
查看本地、遠端所有分支 git branch -a
刪除分支 git branch -D <name>
刪除遠端分支 git push origin --delete <name>
切換分支 git checkout <name>
創建分支並切換 git checkout -b <name>

因爲checkout承擔了太多功能,所以在Git V2.23.0版本,Git新增了switch命令分擔checkout命令切換分支的功能,比如:

操作 命令
切換分支 git switch <name>
切換到先前的分支 git switch -
創建分支並切換 git switch -c <name>
覆蓋創建分支並切換 git switch -C <name>

5 準備commit

當我們需要針對某個功能要對代碼做出改動時,我們先把所有需要改動的地方完成,可能包括以下這些改動:

  1. 文件改名
  2. 修改文件內容
  3. 刪除文件
  4. 新增文件
  5. 等等...

我們通過git add指明在提交(commit)改動時需要包含哪些改動,這些改動會被保存到暫存區

可以使用git add <目錄>來添加整個目錄,使用git add -u添加所有已經在版本控制中的內容的改動。

在添加改動到暫存區後,我們可以繼續在工作區修改,可能存在下面這些操作:

  1. 某個文件不應該改動或者添加版本控制,那麼可以取消暫存:git reset <file>
  2. 添加暫存後,在工作區又修改了某個文件,想從暫存區恢復:git checkout -- <file>
  3. 某個文件不想修改了,想恢復到最新commit的狀態:git checkout HEAD <file>

在Git V2.23.0版本中,Git還新增了restore命令分擔了部分checkout命令的功能,比如前面撤消改動的三個操作將對應的變成:

  1. 取消暫存:git restore --stage/-S <file>,等同於git restore --source=HEAD --stage/-S <file>
  2. 從暫存區恢復:git restore <file>(沒有指定--source,也沒有使用--stage,表明source爲暫存區)
  3. 取消所有改動:git restore --source=HEAD --staged --worktree

因此,建議升級Git使用restore命令,其參數含義更加明確。

6 提交commit

在前面充足的準備下,我們把所有需要提交的改動添加到了暫存區,那麼我們就可以開始執行提交了。

通過執行git commit,然後就會打開默認的編輯器進行commit message的編寫。

在打開的編輯器內容中默認還會包含目前添加的改動內容,幫助我們確定commit message怎麼書寫,但是因爲這些內容都是"#"開頭的,所以並不會真的出現在最後的commit message中。
爲了良好的管理,編寫commit message最好遵守一定的規則,比如對改動進行分類,劃定範圍,語句使用統一的句式等等。

7 撤銷commit

當我們想要撤銷一個commit時,我們可以使用git reset命令,命令格式爲:

git reset [<mode>] [<commit>]

mode有5個選擇,常用的是前三個,--mixed是不指定mode時的默認參數:

  1. --soft:把撤銷的改動保留到暫存區,不改變工作區的內容;
  2. --mixed:撤銷的改動不會保留到暫存區,也不改變工作區的內容;
  3. --hard:撤銷的改動不會保留在暫存區,而是直接應用到工作區,相當於執行--soft之後,再從暫存區checkout;
  4. --merge:更多用在撤銷一個merge,這時會直接修改工作區,需慎用;
  5. --keep:類似--hard,但是如果工作區有了改動,那麼會中止reset。

對於--hard如果工作區有的文件改動和提交了的內容不一致,那麼工作區的改動將會被覆蓋;如果不確定怎麼操作,建議執行--soft,再選擇要保留(checkout)或者丟棄(reset)哪些改動。

8 “修改”commit

雖然提交前做了充足的準備,但是總是可能出現一些意外,比如:

  1. 發現commit message出現了typo,顯得非常不合適,必須改過來;
  2. 有新增的文件沒有添加;
  3. copy別人的代碼忘記改author;
  4. 等等...

那麼此時可以把需要改動的地方修改完成,同樣通過git add添加暫存,然後使用git commit --amend進行提交,並重新修改commit message即可。

也可以直接執行git commit --amend去修改commit message。

其實這個操作並不是修改commit,而是撤銷原先的commit,並重新創建了一個新的commit,並且獲取了此前的commit message,相當於:

$ git reset --soft HEAD^
$ ... do something else to come up with the right tree ...
$ git commit -c ORIG_HEAD

9 管理tag

在比較重要的版本上,我們可能需要創建標籤,使用的命令是git tag,常用的命令有下面這些:

操作 命令
顯示tag git tag
顯示匹配tag git tag -l "v1.0.*"
查看tag信息 git show <tag-name>
添加輕量tag git tag "v1.0.0"
添加註解tag git tag -a "v1.0.0" -m "tag message"
指定commit添加tag git tag -a "v1.0.0" -m "tag message" <commit-id>
刪除tag git tag -d "v1.0.0
刪除y遠端tag git push origin :refs/tags/v1.0.0
推送tag git push origin v1.0.0
推送所有tag git push origin --tags

打標籤的操作相對獨立;-m如果沒有指定,則會打開編輯器讓用戶輸入tag message。

10 拉取和推送改動

使用git pull命令拉取改動,命令格式爲:

$ git pull <遠程主機名> <遠程分支名>:<本地分支名>

比如,要獲取遠程origin主機上的remote_master分支作爲本地的master分支:

$ git pull origin remote_master:master

如果不指定本地分支名,則表示是當前分支;
如果本地分支和遠程分支有綁定關係,並且只綁定了一個遠程分支,則命令可簡化爲:

$ git pull

綁定遠端分支可以通過命令:

git branch --set-upstream master origin/remote_master

使用git push命令推送改動。命令格式和git pull類似,但是本地分支名和遠端分支名互換了位置,爲:

$ git push <遠程主機名> <本地分支名>:<遠程分支名>

比如將本地master分支推送到遠端remote_master分支,命令爲:

$ git push origin master:remote_master

git pull類似,如果本地分支和遠程分支有綁定關係,並且只綁定了一個遠程分支,則命令可簡化爲:

$ git push

Git並不複雜,可以本地建立一個倉庫多加練習,實際工作中保持合理的使用流程,還是很好用的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章