我的 Git 備忘單

shix_112發表於2017-04-15

我的 Git 備忘單


0. Git 基本概念

0.1 Git 與 SVN 區別

1. Git 是分散式版本控制系統,SVN 是集中式版本控制系統;
2. Git 把內容按照後設資料方式儲存,每次提交的檔案全部內容(snapshot)都會記錄,SVN 是按照檔案儲存的,儲存每次提交(commit)之間的差異;
3. Git 的分支是在同一個工作目錄下的,SVN 的分支就是版本庫中的一個目錄;
4. Git 沒有一個全域性的版本號,SVN 的版本號是全域性的;
5. Git 使用SHA-1雜湊演算法確保程式碼內容的完整性以及出問題時對版本庫最低的破壞,SVN 相比就差一些。

0.2 Git 物件

1. 所有用來表示專案歷史資訊的檔案,是通過一個40個字元的(40-digit)“物件名”來索引的,物件名看起來像這樣: 
                 3ff87c4664981e243g625791c8ea3bbb5f2279a3。
   每一個“物件名”都是對“物件”內容做SHA1雜湊計算得來的,從而保證兩個不同內容的物件不可能有相同的“物件名”
2. 每個物件(object) 包括三個部分:型別(blob、tree、commit 和 tag)、內容(內容取決於物件的型別)和內容大小。
  2.1 blob   -- 用來儲存檔案資料,通常是一個檔案;
  2.2 tree   -- 類似目錄,用來管理一些 tree 和 blob;
  2.3 commit -- 一個 commit 只指向一個 tree,標記專案某一個特定的時間點狀態,包括
                一些時間點的是後設資料,如 時間戳、最後一個提交者等;
  2.4 tag    -- 標記某一個 commit 的方法。

0.3 Git 使用時的資料轉換

# git 的四區 :工作區、暫存區、本地倉庫及遠端倉庫及其使用時的關係。
#
#      工作區                  暫存區                  本地倉庫                遠端倉庫
#  (workspace)             (index)           (local repository)   (remote repository) 
#        |  ---> add (-u) --->  |                        |                      |
#        |  <--- checkout <---  |                        |                      |
#        |  <---   diff   --->  |                        |                      |
#        |   rm --cached  <---  |                        |                      |
#        |                      |  --->   commit   --->  |                      |
#        |                      |  <--- reset HEAD <---  |                      |
#        |  <------------    diff HEAD   ------------->  |                      |
#        |  ------------>    commit -a   ------------->  |                      |
#        |  <------------  checkout HEAD <-------------  |                      |
#        |                      |                        |  --->   push   --->  |
#        |                      |                        |  <---  fetch   <---  | 
#        |  <------------      merge     <-------------  |                      | 
#        |  <------------           pull or rebase               <------------  | 

1. 命令

1.1 開始

1.1.1 當前資料夾初始化為 git 本地倉庫
  $git init
1.1.2 從遠端 git 倉庫獲取程式碼
  $git clone url

1.2 配置

1.2.1 設定命令列顯示顏色
  $git config --global color.ui true
1.2.1 設定 push 到遠端 分支時, 預設 push 的本地分支
  $git config --global push.default current
1.2.1 設定預設的編輯器
  $git config --global core.editor vim
1.2.1 設定使用 git 時預設的使用者名稱(一般設定為名字或工號)
  $git config --global user.name "user_name"
1.2.1 設定使用 git 時預設的郵箱名(一般設定為公司內的郵箱)
  $git config --global user.email "user_name@126.com"
1.2.1 設定預設的 git diff 時比較工具
  $git config --global diff.tool diff3

1.3 本地分支操作

1.3.1 檢視所有本地分支
  $git branch
1.3.2 切換到一個已經存在的本地分支
  $git checkout local_branch_name
1.3.3 從本地分支切換到一個新建的分支 new_branch_name
  $git checkout -b new_branch_name
1.3.4 合併 other_branch_name 名的分支到當前分支(不保留被合併分支的歷史資訊)
  $git merge other_branch_name
 #feature 分支合併到當前分支 develop:git merge feature
 #  | <- develop -> |
 #  |               |
 # A.1 --> A.2 --> A.3 -- B.1 --> B.2 --> B.3 
 #                        |               |
 #                        | <- feature -> |
1.3.5 合併 other_branch_name 名的分支到當前分支(保留被合併分支的歷史資訊)
  $git merge –no-ff other_branch_name
#feature 分支合併到當前分支 develop:git merge –no-ff feature
#   | <- develop -> |
#   |               |
#  A.1 --> A.2 --> A.3 ------------------------> C.1
#                   |                            |
#                   | --> B.1 --> B.2 --> B.3 -->|
#                        |               |
#                        | <- feature -> |
1.3.6 刪除本地分支 branch_name(非強制刪除,分支未合併時,會提示)
  $git branch -d branch_name
1.3.7 刪除本地分支 branch_name (強行刪除分支,不做任何提示,類似 rm -rf)
  $git branch -D branch_name

1.4 更新當前分支

1.4.1 檢視所有提交
  $git log
1.4.2 展示好看一些的查詢
  $git log --pretty=format:"%h %s" --graph
1.4.3 檢視 user_name 使用者過去一週做過什麼
  $git log --author=`user_name` --after={1.week.ago} --pretty=oneline --abbrev-commit
1.4.4 檢視所有未被合併過的提交資訊(假如該分支是從 master 建立的)
  $git log --no-merges master..
1.4.5 檢視當前分支名稱
  $git branch
1.4.6 檢視當前分支的狀態
#比 git status 更簡潔化的一個命令
  $git status -s 
1.4.7 增加指定檔名 file_name 到待提交的 list 中
  $git add file_name  
1.4.8 增加所有未提交的檔案 到待提交的 list 中
  $git add .
1.4.8 增加指定型別 .txt 格式的到待 提交的 list 中。
  $git add `*.txt`
1.4.9 讓 git 不再 提交指定的檔案 file_name
  $git rm file_name
1.4.10 使用 git 預設的編輯器將待提交的 list 中檔案提交
  $git commit
1.4.11 通過命名行的模式將待提交的 list 中檔案提交
  $git commit -m `your commit msg`
1.4.12 修改已經提交但是未 push 到遠端的提交 msg
  $git commit --amend

1.5 高階命令

1.5.1 回退到上個版本,只保留原始碼
  $git reset
1.5.2 回退到上個版本,本地的原始碼也會變為上一個版本的內容
  $git reset --head HEAD
1.5.3 當前分支情況下,回退到指定的歷史
  $git reset tag
  $git reset commit_hash
1.5.4 暫存當前的變更,不提交
  $git stash
1.5.5 取出暫存的變更到當前分支
  $git stash pop
1.5.6 撤銷當前分支下對某個檔案的變更
  $git checkout file_name

1.6 比較變更

1.6.1 顯示工作目錄與索引區檔案之間的差異
  $git diff
1.6.2 顯示工作目錄與git倉庫之間的差異
  $git diff HEAD
#比較上次提交
  $git diff HEAD^
#比較上2次提交
  $git diff HEAD~2
1.6.3 當前分支與 other_branch_name 分支進行比較
  $git diff other_branch_name
1.6.4 使用配置檔案中的比較工具進行比較(和 git diff 類似)
  $git difftool
1.6.5 檢視當前分支與目標分支的檔案變更
  $git diff --no-commit-id --name-only --no-merges origin/master..
1.6.6 檢視當前分支檔案變更的狀態
  $git diff --stat

1.7 遠端分支操作

1.7.1 檢視本地倉庫有哪些遠端連線(帶 url 地址)
#備註: 當 git clone 一個倉庫的時候,會自動建立一個別名為 origin 的遠端連線到 clone 的倉庫。
  $git remote -v
1.7.2 建立一個連線到遠端倉庫的連線(假如 origin 沒有設定)
  $git remote add remote_origin_name https://one_git_remote_url
1.7.3 當前分支 push 到 遠端分支 – 1
#上傳本地所有分支程式碼到遠端對應的分支上
  $git push
1.7.3 當前分支 push 到 遠端分支 – 2
#當前分支與多個主機存在追蹤關係,則可以使用 -u 選項指定一個預設主機,後面就可以不加任何引數使用 git push。
  $git push -u orgin master
1.7.4 當前分支 push 到 遠端分支 – 3
#上傳本地當前分支程式碼到 master 分支
  $git push origin master
1.7.4 獲取遠端對應分支更新到本地
  $git pull
1.7.5 獲取遠端指定分支名 branch_name 到本地
  $git pull origin branch_name
1.7.6 獲取遠端分支的更新歷史 – 1
  $git fetch 
1.7.7 獲取遠端分支的更新歷史 – 2
#假如遠端分支有被刪除,此命令也會把本地對應的分支刪除。
  $git fetch --prune 
1.7.8 獲取遠端更新併合併到當前分支
#此組合命令,和 git pull 的作用一樣的。
#git fetch 獲取遠端分支到本地,不合併到當前分支。
#儘量少用git pull,多用git fetch和merge。
  $git fetch && git merge origin/remote_branch_name
1.7.9 檢視遠端所有分支
  $git branch -a

2. 一些資料

2.1 git 命令線上學習

  https://try.github.io

2.2 git 分支線上學習

  http://learngitbranching.js.org/?NODEMO

2.3 《Pro Git》 線上免費書

2.3.1 英文原版
  https://git-scm.com/book/en/v2
2.3.2 中文版
  http://git.oschina.net/progit/

2.4 《Git 權威指南》 線上免費書

  https://github.com/gotgit/gotgit/

3. git 歷史檢視工具

3.1 SourceTree

  https://www.sourcetreeapp.com/

3.2 TortoiseGit

  https://tortoisegit.org/

3.3 命令列下的 Git 瀏覽器

3.3.1 官網

  https://jonas.github.io/tig/
3.3.2 安裝
  $sudo apt-get install tig 
or 
  $brew install tig

3.4 gitk

  http://gitk.sourceforge.net/

3.5 其他

  https://git-scm.com/downloads/guis

4. 一些檔案對比的工具

4.1 Meld

  http://meldmerge.org/

4.2 opendiff

  http://guides.macrumors.com/opendiff

4.3 diff3

  https://en.wikipedia.org/wiki/Diff3

4.4 beyond compare

  http://www.scootersoftware.com/

4.5 P4Merge

  https://www.perforce.com/product/components/perforce-visual-merge-and-diff-tools

4.6 其他(git 配置檔案)

  https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration#External-Merge-and-Diff-Tools

5. git flow

5.1 git flow 模型

  http://nvie.com/files/Git-branching-model.pdf

5.2 git flow on github

  https://github.com/nvie/gitflow

5.3 基於git的原始碼管理模型——git flow

  http://www.ituring.com.cn/article/56870

6. 其他

6.1 命令列我自己常用的 git 歷史查詢的別名

6.1.1 git lg
  lg = log --color --graph --pretty=format:`%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset` --abbrev-commit
6.1.2 git tlg
  tlog = log --stat --since=`1 Day Ago` --graph --pretty=oneline --abbrev-commit --date=relative
6.1.3 git plg
  plog = log --graph --pretty=`format:%C(red)%d%C(reset) %C(yellow)%h%C(reset) %ar %C(green)%aN%C(reset) %s`
6.1.4 git glg
  glog = log --graph --pretty=format:`%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset`

6.3 所有提交者的提交次數排行榜

  rank = shortlog -sn --no-merges

6.3 沒有被 merge 的刪除的分支

  bdm = "!git branch --merged | grep -v `*` | xargs -n 1 git branch -d"

6.4 彩蛋

6.4.1 彩蛋 – 1 (歷史重演)
  $git log --reverse -p
6.4.2 彩蛋 – 2(歷史追溯)
  $git show HEAD~1

參考文獻

https://git-scm.com/doc
http://nvie.com/posts/a-successful-git-branching-model/
https://github.com/gotgit/gotgit/
git: fetch and merge, don’t pull
http://stackoverflow.com/questions/292357/what-is-the-difference-between-git-pull-and-git-fetch