1. 程式人生 > 實用技巧 >Unity 遊戲開發技術學生作品展2014版

Unity 遊戲開發技術學生作品展2014版

Git 基本操作 --> IT 人員必會操作

1,引言

在我們講解 gIt 的時候我們要先了解一個概念,什麼是版本控制?

版本控制是一種記錄一個或若干個檔案內容變化,以便將來查閱特定版本修訂情況的系統。我們可能最常用的就是將一個檔案複製成若干份,然後在檔案結尾寫個標籤,來區別每個特定的版本。我們採用這種方式的時候,會在電腦上存放很多個版本的文件,佔用資源不說,使用的時候也不是特別方便、

1.1 什麼是 GIt?

it是一個開源的分散式版本控制系統,用於敏捷高效地處理任何或大或小的專案(編寫一點點程式就可以合併到master主分支上,然後測試執行它)

Git 是 Linus Torvalds 為了幫助管理 Linux 核心開發而開發的一個開放原始碼的版本控制軟體。 Git 與常用的版本控制工具 CVS, Subversion 等不同,它採用了分散式版本庫的方式,不必 伺服器端軟體支援。

1.2 Git 的核心競爭力

1.2.1,直接記錄快照,而非差異比較

git 和其他版本控制管理系統的主要差別在於 Git 對待資料的方法。從概念上來說,其他大部分系統以檔案變更列表的方式儲存資訊,這類系統(CVS、Subversion、Perforce等),將他們儲存的資訊看做是一組基本檔案和每個檔案隨時間逐步累積的差異。

Git 則不按照上面方式對待活儲存資料。反之,Git 更像是把資料看作對小型檔案系統的一系列快照。在 Git 中,每當你提交更新活儲存專案狀態時,他基本上就會對當時管理的目錄下的全部檔案建立一個快照並儲存這個快照的索引,為了效率,如果檔案沒有修改,Git 不在重新儲存改檔案,而只是保留一個連線指向之前儲存的檔案。Git 對待資料更像是一個快照流

這是 Git 與幾乎其他所有版本控制系統的重要區別。

1.2.2,近乎所有操作都是在本地執行

在 Git 中的絕大多數操作都是需要訪問本地檔案和資源,一般不需要來自網路上其他計算機的資訊。

1.2.3,Git 保證完整性

Git 中所有的資料在儲存前都計算校驗和,然後以校驗和來引用。這意味著不可能在 Git 不知情時更改任何檔案內容或者目錄內容,這個功能構建 Git 底層,是構成 Git 哲學不可缺失的部分。

Git 用以計算校驗和的機制叫做 SHA-1 雜湊(hash,雜湊)。 這是一個由 40 個十六進位制字元(0-9 和 a-f)組成的字串,基於 Git 中檔案的內容或目錄結構計算出來。 SHA-1 雜湊看起來是這樣:

24b9da6552252987aa493b52f8696cd6d3b00373

Git 中使用這種雜湊值的情況很多,你將經常看到這種雜湊值。 實際上,Git 資料庫中儲存的資訊都是以檔案內容的雜湊值來索引,而不是檔名。

1.2.4,Git 一般只新增資料

你執行的 Git 操作,幾乎只往 Git 資料庫中 新增 資料。 你很難讓 Git 執行任何不可逆操作,或者讓它以任何方式清除資料。 同別的 VCS 一樣,未提交更新時有可能丟失或弄亂修改的內容。但是一旦你提交快照到 Git 中, 就難以再丟失資料,特別是如果你定期的推送資料庫到其它倉庫的話。

1.3,Git的三種狀態

Git 有三種狀態,你的檔案可能處於其中之一: 已提交(committed)已修改(modified)已暫存(staged)。只要是被 Git 管理的檔案都會處於這三種狀態之間的一種。

  • 已提交(committed):表示資料已經安全的儲存在本地資料庫中。
  • 已修改(modified):表示修改了檔案,但還沒儲存到資料庫中。
  • 已暫存(staged):表示對一個已經修改檔案的當前版本做了標記,使之包含在下次提交的快照中。

基本工作流程:

1,在工作目錄中修改檔案

2,暫存檔案,將檔案的快照放入暫存區域

3,提交更新,找到暫存區域的檔案,將快照永久性儲存的 Git 倉庫目錄。

1.4,Git和SVN的區別

  1. Git是分散式的,SVN是集中式的。這是Git和其他非分散式的版本控制系統,例如SVN,CVS等,最核心的區別。(Git是每個工作人員的電腦都可以作為一個倉庫,不管你有沒有網路,人在哪個地方你都可以正常的工作,但是SVN他所有的程式碼都集中的放到一個遠端倉庫裡,你必須能訪問這個,才可以對程式碼進行修改提交)
  2. Git把內容按元資料方式儲存,而SVN是按檔案目錄儲存(你在本地什麼樣,上傳到SVN上就是什麼樣);所有的資源控制系統都是把檔案的元資訊隱藏在一個類似.svn,.cvs等的資料夾裡
  3. Git分支和SVN 的分不同:分支在 SVN 中一點不特別,就是版本庫中的另外一個目錄
  4. Git沒有一個全域性的版本號。而SVN有:目前為止這是跟SVN相比 Git缺少的最大的一個特徵
  5. git的內容完整性要優於SVN:Git的內容儲存使用的事SHA-1雜湊演算法。這能確保程式碼內容的完整性,確保在遇到磁碟故障和網路問題時降低對版本庫的破壞

2,安裝 git

2.1,在 Linux 上安裝

如果你想在 Linux 上用二進位制安裝程式來安裝 Git,可以使用發行版包含的基礎軟體包管理工具來安裝。

sudo yum install git

基於 Debian 的發行版上:

sudo apt-get install git

2.2,在 Mac 上安裝

可以參考官方檔案安裝手冊去安裝:https://git-scm.com/download/mac

2.3,在 windows 上安裝

和安裝其他軟體沒有什麼區別,我們去 git 官網上面下載對應的 windows 版本的軟體,一步一步安裝即可

https://git-scm.com/downloads

3,使用 Git

下面我們開始介紹使用 Git 來進行版本管理,整個流程我會按照工作中一個專案的開發流程來往下面走。

3.1,配置 Git

通過上面的安裝,我相信安裝這一步對大家都沒什麼困難,一個軟體安裝好了,我們要配置下他的一些配置檔案,Git 自帶一個 git config的工具來幫助設定控制 Git 外觀和行為的配置變數,這些變數儲存在三個不同的位置:

  1. /etc/gitconfig :包含系統上每一個使用者及他們倉庫的 通用 配置。如果使用帶有 --system 選項的 git config時,他會從此檔案讀取配置變數
  2. ~/.gitconfig 或 ~/.config/git/config 檔案:只針對當前使用者。 可以傳遞 --global 選項讓 Git 讀寫此檔案。
  3. 當前使用倉庫的 Git 目錄中的 config 檔案(就是 .git/config):針對該倉庫。

配置檔案優先順序從低到高排列如下:優先順序高的會覆蓋優先順序低的檔案內容

/etc/gitconfig ----->  ~/.gitconfig ----->  .git/config

3.1.1,配置使用者資訊

當安裝完 Git 應該做的第一件事就是設定我們自己的使用者名稱與郵件地址。因為每一個 Git 的提交都會使用這些資訊,並且他會寫入到你的每一次提交中,因為這樣才知道那個版本是你寫的,

//全域性配置,針對系統上所有的使用者,修改/etc/gitconfig
$ sudo git config --system user.email "[email protected]"
$ sudo git config --system user.name "zhangshoufu"
$ sudo git config --system --list

// 當前使用者設定
$ git config --global user.email "[email protected]"
$ git config --global user.name "zhangshoufu"
$ git config --global --list

//針對當前這個專案
$ git config --local user.email "[email protected]"
$ git config --local user.name "zhangshoufu"
$ git config --local --list 

3.2,Git 初始化(專案初始化)

我們先建立一個 Git 的工作目錄(建立專案寫程式碼的目錄),

$ mkdir ./zsf_git_project

專案目錄建立好了,我們想讓 Git 管理它,肯定要告訴 Git 你要管理那個目錄:

//進入到這個目錄中
$ cd zsf_git_project
//告訴 Git 要管理那個目錄
$ git init
Initialized empty Git repository in /Users/zhumengyuan/zsf_git_project/.git/
// 空倉庫建立完成後git_test目錄下會生成一個.git隱藏資料夾,倉庫 預設包含一個主支,即master分支,預設操作都是在主分支master上進行的
//配置使用者資訊
$ git config --local user.email "[email protected]"
$ git config --local user.name "zhangshoufu"
$ cat .git/config
[user]
	email = [email protected]
	name = zhangshoufu

3.3 Git 的基本操作

3.3.1 檢測當前專案中檔案的改變情況

$ git status 
On branch master //當前所處於的分支

No commits yet

nothing to commit (create/copy files and use "git add" to track)
//建立一個新檔案
$ touch 1.go
//在此檢測目錄中檔案的改變情況
$ git status  
On branch master

No commits yet

Untracked files: //未被跟蹤的檔案,只是在工作目錄建立了
  (use "git add <file>..." to include in what will be committed)

	1.go
//你沒有提交檔案,但是你有存在未跟蹤的檔案,我們可以使用git add 把這個未跟蹤的檔案提交到暫存區
nothing added to commit but untracked files present (use "git add" to track)
//發現當前專案下有一個檔案發生了改變

緊湊型輸出,不顯示多餘的資訊

$ echo "test git status -s " > 1.go
$ touch 1.py
$ git status -s
 M 1.go
?? 1.py

說明:git status -s符號的說明

??: 新新增的未跟蹤檔案前面有 ?? 標記

A : 新新增到暫存區中的檔案前面有 A 標記

M : 修改過的檔案前面有 M 標記。 你可能注意到了 M 有兩個可以出現的位置,出現在右邊的 M (紅色)表示該檔案被修改了但是還沒放入暫存區,出現在靠左邊的 M 表示該檔案被修改了並放入了暫存區。

空: 當工作目錄和暫存區和本地倉庫檔案內容一樣的時候,什麼都不輸出

3.3.2 管理檔案

//只管理1.go 這個檔案
$ git add 1.go
//管理這個專案下面的所有檔案
$ git add .
//支援正則,管理.go 的檔案,其他的不管理
$ git add *.go
$ git status 
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	new file:   1.go
	
//如果你認為直接提交的有問題,你可以使用這個命令把他撤銷下來
$ git rm --cached 1.go

3.3.3,生成版本資訊,把當前暫存區的檔案提交到本地倉庫

git commit -m "使用 git 生成的第一個版本"
[master (root-commit) 3f3ea2a] 使用 git 生成的第一個版本
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 1.go

勤勞和細心的你一定會發現,每一次用git add提交一個新的檔案的時候都會在最下面出現一行create mode 100644 File_Name這句話,那麼100644這串數字代表什麼含義呢?下面經過試驗來看一下

100 代表普通檔案(regular file)
644 為許可權
也可以去這個檔案裡面檢視/usr/share/doc/git-1.8.3.1/technical/index-format.txt

  32-bit mode, split into (high to low bits)

    4-bit object type
      valid values in binary are 1000 (regular file), 1010 (symbolic link)
      and 1110 (gitlink)

    3-bit unused

    9-bit unix permission. Only 0755 and 0644 are valid for regular files.
    Symbolic links and gitlinks have value 0 in this field.

3.3.4,檢視提交的日誌

$ git log
commit 3f3ea2a92fc386383ffd0bd7decacd3e8ec3c06b (HEAD -> master)
Author: zhangshoufu <[email protected]>
Date:   Wed Jul 15 08:13:26 2020 +0800

    使用 git 生成的第一個版本

檢視最近一次 commit 提交資訊

$ git log -p -1

另外一個常用的選項是 --pretty。 這個選項可以指定使用不同於預設格式的方式展示提交歷史。 這個選項有一些內建的子選項供你使用。 比如用 oneline 將每個提交放在一行顯示,檢視的提交數很大時非常有用。 另外還有 short,full 和 fuller 可以用,展示的資訊或多或少有些不同,請自己動手實踐一下看看效果如何。

$ git log --pretty=oneline
ca82a6dff817ec66f44342007202690a93763949 changed the version number
085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 removed unnecessary test
a11bef06a3f659402fe7563abf99ad00de2209e6 first commit

但最有意思的是 format,可以定製要顯示的記錄格式。 這樣的輸出對後期提取分析格外有用 — 因為你知道輸出的格式不會隨著 Git 的更新而發生改變:

$ git log --pretty=format:"%h - %an, %ar : %s"
ca82a6d - Scott Chacon, 6 years ago : changed the version number
085bb3b - Scott Chacon, 6 years ago : removed unnecessary test
a11bef0 - Scott Chacon, 6 years ago : first commit

顯示所有的更改操作

$ git reflog 

圖形化顯示 log 日誌

$ git log --graph
$ git log --graph --pretty=format:"%h %s"

3.3.5 撤銷

//測試檔案準備
$ cat test_file 
test git status -s 
test git diff 
$ echo 'test git checkout -- ' >> test_file 
$ cat test_file 
test git status -s 
test git diff 
test git checkout -- 
$ git add test_file
$ git diff test_file
$ git diff --cached test_file
diff --git a/test_file b/test_file
index 8072794..d92353f 100644
--- a/test_file
+++ b/test_file
@@ -1,2 +1,3 @@
 test git status -s 
 test git diff 
+test git checkout --
//環境模擬成功,現在就是暫存區和本地目錄一致,和本地倉庫不一致

//從本地倉庫撤銷到暫存區,撤銷到最後一次commit
[root@zsf_node3 git_test]# git reset HEAD test_file 
Unstaged changes after reset:
M       test_file
//我們可以通過這個命令可以看出開我們已經把檔案從本地倉庫撤銷到暫存區了
[root@zsf_node3 git_test]# git diff
diff --git a/test_file b/test_file
index 8072794..d92353f 100644
--- a/test_file
+++ b/test_file
@@ -1,2 +1,3 @@
 test git status -s 
 test git diff 
+test git checkout -- 

//把檔案從暫存區撤銷到工作目錄
[root@zsf_node3 git_test]# git checkout -- test_file
[root@zsf_node3 git_test]# cat test_file 
test git status -s 
test git diff 
//發現我們剛才追加進去的內容已經不存在了

diff比較的符號說明
+ 檔案裡面有新增的內容
- 檔案裡面刪除了內容
如果是替換的話,他換先刪除原先的行,在把更改後的行增加上去

//從本地倉庫拉去指定commit的檔案
[root@zsf_node3 git_test]# git reflog       //先檢視所有commit的記錄
e98d2e5 HEAD@{0}: commit: test git diff
bb0deb3 HEAD@{1}: commit: git status -s test
6182c28 HEAD@{2}: commit (initial): test commit add test_file

//直接從本地倉庫撤銷到工作目錄
[root@zsf_node3 git_test]# git reset --hard 6182c28
HEAD is now at 6182c28 test commit add test_file[root@zsf_node3 git_test]# git diff 
[root@zsf_node3 git_test]# cat test_file 
[root@zsf_node3 git_test]# 

3.3.6, 跳過暫存區,直接把檔案提交到本地倉庫

$ git  commit -a -m "test git commit -a"
[master b140339] test git commit -a
 1 file changed, 1 insertion(+)
 //把所有被git跟蹤的檔案直接提交到本地倉庫
$ git commit -a -m "test git commit -a " test_file
fatal: Paths with -a does not make sense.
// 如果這個檔案沒有被git跟蹤,是不能跳過space暫存區域的

3.3.7,移除檔案

從git中移除某個檔案,就必須要從已經跟蹤檔案清單中移除(從暫存區移除),然後commit提交。我們可以使用git rm命令完成此項工作,並連帶衝工作目錄中刪除指定的檔案,這樣以後就不會出現在未跟中檔案清單中了。

如果只是簡單地從工作目錄中手工刪除檔案,執行git status就會在“Changes not staged for commit”部分(也就是 未暫存清單)

$ rm -f test_file 
$ git status 
On branch master
Changes not staged for commit:  未提交的更改
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        deleted:    test_file

no changes added to commit (use "git add" and/or "git commit -a")

//然後執行git rm 刪除
$ git rm test_file
rm 'test_file'
$ git status 
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        deleted:    test_file
//當下次再提交的時候test_file 這個檔案就完成了刪除了

$ git commit  -a -m "delete test_file"
[master 47a2f61] delete test_file
 1 file changed, 1 deletion(-)
 delete mode 100644 test_file
$ git status
On branch master
nothing to commit, working tree clean

如果刪除之前修改過並且已經放到暫存區域的話,則必須要用強制刪除選項 -f(譯註:即 force 的首字母)。 這是一種安全特性,用於防止誤刪還沒有新增到快照的資料,這樣的資料不能被 Git 恢復。

只刪除本地倉庫裡面的,不刪除本地工作目錄中的檔案

$ git rm --cached test_file
rm 'test_file'
$ ls 
test_file
$ git status 
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        deleted:    test_file

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        test_file

Git 批量刪除檔案

git rm *.log 支援萬用字元

3.3.8,移動檔案,更改檔名

//更改檔名稱
$ git mv test_file file_test
$ git status 
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        renamed:    test_file -> file_test
$ ls 
file_test

執行了上面這個命令相當於執行了下面這三個命令
$ mv test_file  file_test
$ git rm test_file
$ git add file_test

3.3.9 切換到指定版本

$ git reflog 
$ git reset --hard 版本號

3.3.10 Git操作示意圖

4, 遠端倉庫

我們上面的所有操作都是在自己的本地電腦上面完成的,還是沒有辦法進行多人協作開發,當前電腦出問題之後那版本就沒有了,現在我們改一下我們的套路

我們這邊使用Github做演示,gitlab 和他大致相同。

4.1,什麼是GitHub

GitHub 是最大的 Git 版本庫託管商,是成千上萬的開發者和專案能夠合作進行的中心。 大部分 Git 版本庫都託管在 GitHub,很多開源專案使用 GitHub 實現 Git 託管、問題追蹤、程式碼審查以及其它事情。 所以,儘管這不是 Git 開源專案的直接部分,但如果想要專業地使用 Git,你將不可避免地與 GitHub 打交道,所以這依然是一個絕好的學習機會。

4.2,建立Github賬號

你所需要做的第一件事是建立一個免費賬戶。 直接訪問 https://github.com,選擇一個未被佔用的使用者名稱,提供一個電子郵件地址和密碼,點選寫著“Sign up for GitHub”的綠色大按鈕即可。

4.3,操作

剩下的相關操作可以檢視官方文件:https://git-scm.com/book/zh/v2/GitHub-%E8%B4%A6%E6%88%B7%E7%9A%84%E5%88%9B%E5%BB%BA%E5%92%8C%E9%85%8D%E7%BD%AE

5,Git分支

5.1,建立與合併分支

版本回退裡,你已經知道,每次提交,Git都把它們串成一條時間線,這條時間線就是一個分支。截止到目前,只有一條時間線,在Git裡,這個分支叫主分支,即master分支。HEAD嚴格來說不是指向提交,而是指向mastermaster才是指向提交的,所以,HEAD指向的就是當前分支。

一開始的時候,master分支是一條線,Git用master指向最新的提交,再用HEAD指向master,就能確定當前分支,以及當前分支的提交點:

每次提交,master分支都會向前移動一步,這樣,隨著你不斷提交,master分支的線也越來越長。

當我們建立新的分支,例如dev時,Git新建了一個指標叫dev,指向master相同的提交,再把HEAD指向dev,就表示當前分支在dev上:

你看,Git建立一個分支很快,因為除了增加一個dev指標,改改HEAD的指向,工作區的檔案都沒有任何變化!

不過,從現在開始,對工作區的修改和提交就是針對dev分支了,比如新提交一次後,dev指標往前移動一步,而master指標不變:

假如我們在dev上的工作完成了,就可以把dev合併到master上。Git怎麼合併呢?最簡單的方法,就是直接把master指向dev的當前提交,就完成了合併:

所以Git合併分支也很快!就改改指標,工作區內容也不變!

合併完分支後,甚至可以刪除dev分支。刪除dev分支就是把dev指標給刪掉,刪掉後,我們就剩下了一條master分支:

真是太神奇了,你看得出來有些提交是通過分支完成的嗎?

//建立分支
git branch dev
//切換分支到dev
git checkout dev
// 建立分支並切換到dev分支
git branch -b dev
//檢視當前所處的分支
git branch

我們在dev分支上更改下master上面的一個檔案

echo "this is dev" >> readme.txt
git add . 
git commit -am "test checkout dev"

我們切換到master分支上,發現剛才我們更改的檔案內容在這邊並未顯示,因為我們當前的HEAD 還是指向masterv3版本的,

如果我們想在master上面看到對應的內容,我們需要把dev分支的內容合併到master上

git checkout master
git  merge dev
//需要注意,我們當前是把dev合併到master上,所以我們要在master 上面進行merge

5.2 刪除分支

當我們知道這個分支沒有用的時候,我們可以使用下面命令將其刪除

git branch -d dev

通過工具解決衝突

1,安裝 beyond compare

2,在 GIt 中配置beyond compare

git config --local merge.tool bc4
git config --local mergetool.path "/usr/local/bin/bcomp"
git config --local mergetool.keepBackup false

3,解決衝突

git mergetool