複習 git
$ git init
$ git add .
$ git commit -m 'Initial commit' --author="andyyou<andyyu0920@gmail.com>"
$ git commit --amend
# 包含 delete rename 的變更到索引
$ git add -A .
$ git rm
$ git mv
- Working tree 工作目錄即目前的資料夾
- index 為 git 系統索引:把檔案加入索引又稱為 stage 或 cache
- 每次 commit 只會把 stage 的變更加到 repository
- git 會將目錄中的檔案或資料夾分成 3 類
- tracked 1.1. modified 1.2. unmodified
- ignored
- untracked
# 顯示目前檔案的分類狀況
$ git status
- git 的設定檔有 3 個層級,優先順序如下:
- 專案:該目錄下
.git
中的 config -git config -l
- 系統使用者:家目錄下的
.gitconfig
-git config -l --global
- 系統全域:/etc/gitconfig 使用 brew 安裝則是在 /usr/local/etc -
git config -l --system
- 專案:該目錄下
# 直接編輯 git config,--system, --global(使用者)
$ git config --system -e
# 顯示全部的設定
$ git config -l
$ git config --global user.email 'andyyu0920@gmail.com'
$ git config --global user.name 'andyyou'
# 值沒有空白時可以省略 ''
$ git config --global --unset user.name
- 使用
.gitignore
可以忽略追蹤檔案。.gitignore
本身是否要被忽略則視情況加入。 !
排除檔案#
註解
# 加入 .gitignore 接著移除追蹤
$ git rm --cached <filename>
# 保留本地檔案,直接讓 git 忽略追蹤
$ git update-index --assume-unchanged <filename>
# 還原追蹤
$ git update-index --no-assume-unchanged <filename>
# 加上 alias 列出被忽略的檔案
$ git config --global alias.ignored = !git ls-files -v | grep "^[[:lower:]]"
- Working Tree / Directory 專案工作目錄
- Stage(Index) 暫存/索引
- Local Repository 本地檔案庫
- Remote Repository 遠端檔案庫
- Stash 儲藏
Stash <-> Working Tree <-> Staging <-> Repository
- git reset 意義為把 檔案庫 還原到某版本的狀態。
- 預設
--mixed
檔案庫和索引 會受到影響 --soft
只有檔案庫會變動--hard
工作目錄,檔案庫,索引都會回到某版本的狀態。
- 預設
- git reset HEAD 的意義為把 檔案庫 和 索引(staging) 還原到當前檔案庫版本 = 取消 staging 的變動。但在 git init 的時候沒有任何版本可以還原,所以才會區分下面兩種處理方式
- 取消 staging 分成兩種狀況
- 沒有任何 commit,git init 時 -
git rm --cached
,停止 track 檔案,檔案庫如果有該檔則送出 delete 的索引,否則直接刪除索引。 - 有 commit -
git reset HEAD <filename>
- 沒有任何 commit,git init 時 -
- git rm --cached 意義為在 索引(staging) 加上 刪除的狀態並
停止
追蹤檔案,檔案庫沒有該檔案時直接移除 索引(staging)。 - git rm 會執行 2 個檢查,如果有 staging 存在則放棄執行,working tree 的內容和 repositroy 不同時也無法刪除。
# 把 檔案庫 還原到某版本的狀態,參數包含 只動 檔案庫,檔案庫+索引,檔案庫+索引+工作目錄
$ git reset HEAD --hard
# 新增 commit 並把指定的
$ git revert <commit-ish>
# 查詢某個 commit 的檔案列表
git ls-tree --name-only -r faeaa8
# 查詢某個 commit 的檔案 變更列表
$ git diff-tree --no-commit-id --name-only -r faeaa8
# 搜尋某版中檔案的字串(區分大小寫)
$ git grep 'String You Want' <commit-ish>
# AND
$ git grep -e 'String 1' --and -e 'String 2'<commit-ish>
# OR
$ git grep -e 'String 1' -e 'String 2' <commit-ish>
# 查詢檔案中的每一行由誰修改
$ git blame <filename>
$ git log
$ git log --author="A"
$ git log --shortstat
$ git log --oneline
$ git shortlog
$ git log --graph --decorate --oneline
# 列出工作目錄或索引的檔案
$ git ls-files
# 查詢某分支的演進
$ git reflog <branch name>`
HEAD
可以被簡寫為@
-git reset @
HEAD^
HEAD 的上一版,^1
分支 1 的上一版,^2
分支 2 的上一版。HEAD~2
$ git tag <name> <commit-ish>
$ git tag -d <name>
$ git push origin master --tags
# 工作目錄 <-> 索引
$ git diff
# commit 1 <-> commit 2
$ git diff <commit-1> <commit-2>
# 索引 <-> HEAD commit
$ git diff --cached
git checkout
時,如果取出檔案時
和最新的 commit 不同,會自動加入 索引。這邊指的是指定某個檔案 e.g.git checkout <commit-ish> <filename>
。- 取檔的順序是
- index
- 從最新版的 commit 開始往回找。
git checkout
的本質是取出檔案庫的檔案版本到工作目錄,所以可以用來取消在工作目錄的變更是因為使用某版本的檔案覆蓋到已執行的編輯
(use "git checkout -- <file>..." to discard changes in working directory)
# 取出某次 commit 的檔案資料(會覆蓋工作目錄當前的檔案)
$ git checkout <commit-ish> <filename>
# 為了避免 commit 錯誤的資料,checkout 時應配合 reset
# 注意: checkout file 時如果檔案和最新的 commit 不同會自動加入 stage
$ git checkout <commit-ish> <filename>
$ git reset HEAD <filename>
git stash save
執行 2 個動作- 儲存工作目錄和檔案庫最新版的差異
- 把工作目錄還原為檔案庫最新版
$ git stash save
# 列出暫存
$ git stash list
# 取回暫存
# 1. 取回暫存時比對的版本
# 2. 取回暫存檔 pop 會移除 stash 中的紀錄,apply 不會
$ git checkout <commit-ish>
$ git stash pop/apply
# 移除 stash
$ git stash drop 1
$ git stash clear
$ git gc
$ git gc --aggressive
- 切換分支時,除了被追蹤的檔案,對於 untracked 和 ignored 的檔案 git 完全不會處理。
- 切換分支時,如果有被追蹤的檔案有異動且尚未被 commit 會有兩種情形:
- 比對當前的版本和要切換的版本是否一致,如果一致則 異動 會被保留並切換。
- 如果不同則停止切換。強制切換
git checkout -f
異動
會被清除。
# 列出分支
$ git branch
$ git branch --list bug/*
# 基於某個版本 建立分支
$ git branch <branch name> <commit-ish>
# 建立分支,並切換
$ git checkout -b <branch name>
# 刪除已合併本地分支
$ git branch -d <branch name>
# 強制刪除
$ git branch -D <branch name>
# 重新命名分支
$ git branch -m <new name>
# 取得遠端的分支到本地
$ git checkout -b serverfix origin/serverfix
# 刪除遠端分支
$ git push origin :serverfix
當 checkout
到某分支非最新版
時就會進入 Detached HEAD
狀態。如果又在此時 commit 則會產生出無名分支。
# 刪除無名分支
$ git branch <branch name>
$ git checkout master
$ git branch -D <branch name>
- 合併分成
- fast-forward 快轉 - 合併分支時,原本分支並沒有變動就會使用快轉。強迫不使用快轉
git merge --no-ff <branch name>
- 3 way merge 留下合併紀錄
- fast-forward 快轉 - 合併分支時,原本分支並沒有變動就會使用快轉。強迫不使用快轉
# 在當前的分支,把 <branch name> 複製到當前的分支。
$ git merge <branch name>
# 如果衝突要放棄
$ git merge --abort
Cherry-Pick 也是一種合併,Merge 處理的對象是分支
,Cherry-Pick 處理的是 commit 節點。
- 預設情況下
git cherry-pick
會建立一個新的 commit。 - 使用 cherry-pick 之前所有檔案都要 commit 完成。
$ git cherry-pick <commit-ish>
# If conflicts
# 處理完衝突
$ git cherry-pick --continue
# OR
$ git cherry-pick --abort
當兩分支同時演進,期間需要互相更新時,為了避免兩個分支相互交錯可以使用 rebase。
$ git rebase <branch name>
$ git rebase --continue
$ git rebase --abort
- 設定 git config --system, --global
- git config -l
- git config --system -e
- 取消 staging 的兩種狀況與原理
- git update-index --assume-unchanged
<filename>
- 儲藏的應用 git stash save, list, pop/apply, drop, clear
- 還原的兩種方式 差異
- git ls-tree --name-only -r
<commit-ish>
用途 - git diff-tree --no-commit-id --name-only -r
<commit-ish>
- git log --graph --oneline --decorate
- git ls-files
- @, ^, ~ 的意義與差別
- 差異比對的 3 種狀況
- git checkout 取出檔案需注意的事
- gc
- 切換分支需注意的事
- Detached HEAD
- merge 的兩種情形
- 切換分支,檔案追蹤與否的處理方式
- checkout 取檔 stage 的狀況
- Detached HEAD
- git br --list
- git br -d 分支沒有被合併不能用小 d
- git br -D
- git br