Git的使用與版本控制
所有的素材均來自於https://morvanzhou.github.io/tutorials/others/git/。本文只是個人學習的筆記記錄,如果想要學習,強烈建議去聽聽Morvan老師的課程,一聽就懂,一學就會。
基本配置與操作
創建版本庫 (init)
- 通過iTerm2 cd到版本庫所在的文件夾下
- 通過命令
$ git init
來建立新的git管理庫
添加文件管理 (add)
$ git status
用於查看版本庫的狀況(包括文件所處的狀態:untracked/tracked/modified/unmodified…;$ git add [filename]
用於將文件加入版本庫,使之成爲staged狀態;$ git add .
可以將文件夾中所有未被添加的文件加入版本庫;
提交改變 (commit)
$ git commit -m "comment"
命令將staged狀態的文件commit成umodified狀態,利用comment來註釋本次修改的內容,以便後期查閱
修改記錄
log
$ git log
可以查看詳細的修改記錄$ git log --oneline
可以查看修改記錄的簡要信息
status
$ git status
用於查看版本庫的狀況(包括文件所處的狀態:untracked/tracked/modified/unmodified…$ git status -s
可以查看縮略版的版本庫狀況
diff
$ git diff
用於查看還沒被add,也就是處於unstaged狀態的修改部分和上一個commit的文件的區別$ git diff --cached
用於查看已經被add,也就是處於staged狀態,但是未被commit的修改部分與上一個commit的文件的區別$ git diff HEAD
用於查看已經被add和未被add,但是均爲被commit的內容與上一個commit版本的區別
# 對比三種不同 diff 形式
$ git diff HEAD # staged & unstaged
@@ -1 +1,3 @@
-a = 1 # 已 staged
+a = 2 # 已 staged
+b = 1 # 已 staged
+c = b # 還沒 add 卻 stage (unstaged)
-----------------------
$ git diff # unstaged
@@ -1,2 +1,3 @@
a = 2 # 注: 前面沒有 +
b = 1 # 注: 前面沒有 +
+c = b # 還沒 add 去 stage (unstaged)
-----------------------
$ git diff --cached # staged
@@ -1 +1,2 @@
-a = 1 # 已 staged
+a = 2 # 已 staged
+b = 1 # 已 staged
```
版本回退
amend
在上一個版本中添加一個新文件,可以使用$ git commit --amend --no-edit
來操作,其中的“–no-eit"表示不編輯, 直接合併到上一個 commit
reset
當文件通過add操作後,處於staged狀態後,回到add之前的狀態,可以利用$ git reset [filename]
來實現。其本質是利用reset,使狀態指針回到上一個commit的版本。
- 對於以下情況的記錄,
$ git log --oneline
# 輸出
904e1ba change 2
c6762a1 change 1
13be9a7 create 1.py
```
(1) 回到change2狀態
$ git reset --hard HEAD
(2) 回到change1狀態
$ git reset --hard HEAD^
$ git reset --hard c6762a1
(3) 回到更後面的狀態
$ git reset --hard HEAD~3
表示回到前面第三個狀態,~3表示3個^$ git reset --hard [id]
用狀態id直接回到改狀態
如果回到過去後還想回到將來,可以首先通過$ git reflog
來查看所有對HEAD指針做過的改動,並找到目標的commit id,例如下面這種情況,回到了change 1狀態後,想再回到change 2,可以發現change 2的狀態(在change 2做了amend的行爲,所以id=904e1ba)
$ git reflog
# 輸出
c6762a1 HEAD@{0}: reset: moving to c6762a1
904e1ba HEAD@{1}: commit (amend): change 2
0107760 HEAD@{2}: commit: change 2
c6762a1 HEAD@{3}: commit: change 1
13be9a7 HEAD@{4}: commit (initial): create 1.py
$ git reset --hard 904e1ba
checkout
利用$ git checkout [commit_id] -- [filename]
來指定對某一個file,回到具體某一個commit id時的版本狀態。
分支管理
查看分支
通過$ git log --oneline --graph
可以查看圖形化的master和branch情況
建立分支
分支的作用通常用於開發版本的建立和公開版本的維護。通過分支branch和master的搭配可以在不影響主版本的情況下進行新版本的開發和調試。
branch方法
通過$ git branch [branch name]
的方式進行分支的添加
checkout方法
通過$ git checkout -b [branch name]
的方式可以直接添加一個新的branch並將指針移到該branch中。此外,如果已經建立了新的branch可以通過$ git checkout [branch name]
的方式切換分支
分支中操作
在分支中的修改
$ git commit -am "[comment]"
的方式可以將修改的文件直接add
並進行-m
的comment
操作。這種情況下,如果該文件事先不在repo中是無法操作的(需要amend操作將文件先加入版本庫中)
將分支的內容push到master中
- 首先要切換到master中,才能將branch的內容push過來,用
$ git checkout master
來進行切換 - 使用
$ git mergh --no-ff -m "[comment]" [branch name]
的操作方式,將其他版本的數據合併到當前的master版本中。其中,--no-ff
的參數表示,不使用$ git merge
默認的Fast forward格式進行merge的操作(因爲那樣不會保留commit信息),log中也不會保留graph。
分支衝突的解決
merge方法
當修改同時發生在master(C3)和一個branch(C4)中時,要將master合併branch的內容會產生分支衝突的情況(C4和C3的前序文件信息不同),此時會在master的該文件中報錯:
a = 1
# I went back to change 1
<<<<<<< HEAD
# edited in master ###在master中的信息
=======
# edited in dev ###在被合併的分支中中的信息
>>>>>>> dev
此時,需要將master中的該文件進行手動處理,並提交commit
即可$ git commit -am "solve conflict"
,此時的log文件會顯示出衝突和合並的情況:
$ git log --oneline --graph
# 輸出
* 7810065 solve conflict ###衝突解決後的log信息(和commit id)
|\
| * f7d2e3a change 3 in dev ###*在分支
* | 3d7796e change 4 in master ###*在master
|/
* 47f167e back to change 1 and add comment for 1.py
* 904e1ba change 2
* c6762a1 change 1
* 13be9a7 create 1.py
rebase方法
假設共享的 branch 是 branch B
,而我在 branch A
上工作, 有一天我發現branch B
已經有一些小更新,我也想試試我的程序和這些小更新兼不兼容, 我也我想合併, 這時就可以用 rebase
來補充我的分支branch B
的內容。補充完以後,和後面那張圖的 merge
不同,我還是繼續在 C3
上工作,不過此時的 C3
的本質卻不一樣了,因爲吸收了那些小更新。所以我們用 C3'
來代替。
可以看出 rebase
改變了 C3
的屬性,C3
已經不是從 C1
衍生而來的了。這一點和 merge
不一樣。merge
在合併的時候創建了一個新的 C5
commit
。這一點不同,使得在共享分支中使用 rebase
變得危險。如果是共享分支的歷史被改寫。別人之前共享內容的 commit
就被你的 rebase
修改掉了。
### 在自己的分支上(C3)使用rebase。
$ git rebase [branch name]
### 這時候一定會出現報錯並給予提示:
#When you have resolved this problem, run "git rebase --continue".
#If you prefer to skip this patch, run "git rebase --skip" instead.
#To check out the original branch and stop rebasing, run "git rebase --abort".
###當在自己的branch完成修改後可以選擇以上三種方式,繼續rebase(git rebase --continue)/跳過本次rebase(git rebase --skip)/直接放棄rebase(git rebase --abort)
臨時修改
Stash方法
當在分支上做代碼調試和修改時,突然來了新的需求,這時候需要對手頭的工作進行臨時儲存(不選擇進行直接commit是爲了保持每一次commit的內容都是有價值的,否則之後的log會非常難看)。這時候就可以選擇使用$ git stash
對代碼進行臨時的儲存,然後切換其他分支進行操作完後,回到本分支使用$ git stach pop
調出之前暫存的內容,就可以繼續愉快的coding啦。
在線管理GitHub
對於本地已經git init
了的git管理庫,使用
$ git remote add origin https://github.com/xxx/xxx.git
$ git push -u origin master # 推送本地 master 去 origin
$ git push -u origin dev # 推送本地 dev 去 origin
就可以上傳到在線的github管理庫中了。
over