https://gitbook.tw/chapters/using-git/working-staging-and-repository.html
git init
git clone --bare
僅下載遠端儲存庫回來git init --bare
建立共用儲存庫git clone file:///path/to/repo.git/
checkout 即可--bare
git init
或 git clone
都會一併建立工作區(Workspace / Work Tree)--bare
參數即可乎略(不建立)git work treefatal: this operation must be run in a work tree
--mirror
git hash-object <fileName>
=> 根據檔案內容產生物件名稱commit --amend
)-a
property):以二進制檔案型式儲存-a
property):以文字檔案型式儲存 (不會產生 tag 物件)git cat-file
可以知道 git objects 的類型
git cat-file
看到的 ID 為檔案內容所運算(SHA-1 hash)而來,若 git object 檔名相同(即 ID 相同),則代表檔案內容一致
-t
: type 類型-p
: print 內容-s
: size 檔案大小git add
會將 tracked file 記錄到 git index file(git file status => Staged),並且建立一個 blob 物件(Blob 對象)
git add
有保佑git add
過都會有檔案的 blob,即使沒有 commit 指向它git commit
時,會建立 commit object file,並指向 git index file 中異動檔案的 blob 物件.git/index
檔案.gitkeep
空檔使資料夾加入版控)git fsck
git gc
=> 壓縮到 objects/pack 目錄下,同時會將不常用到的物件刪除
git gc --prune=now
會立刻清除 Unreachable 物件
git gc
+ git prune --expire=now
git add .
後又修改了同一份檔案後再次 git add .
==> 產生兩個 blob 物件,但 commit 僅參考到最後一份 blob 物件,第一份 blob 物件會在 git gc
時被清除從索引內取得檔案 / 資料夾內容
--
請參考:還原
主要用途:將當前分支復原變更
--mixed
| --soft
| --hard
--mixed
[預設值] 工作目錄變更會保留,也就是保留 working directory 中的異動內容 (僅更新索引及指標位置)--soft
工作區目錄變更會保留,同時也保留 index 中的異動內容--hard
工作區檔案內容未 commit 的會被直接還原到指定版本--soft vs. --hard
Reset 模式 | 所在位置(HEAD) | 變更狀態紀錄(INDEX) | 工作目錄 | 說明 |
---|---|---|---|---|
soft | changed | unchanged | unchanged | 僅移除 commit 變成新版未 commit,內容仍是新版的 |
mixed | changed | changed | unchanged | index 移除 staged 標記,變成 Modified or Untracked,內容是新版的 |
hard | changed | changed | changed | 回到上一版版本,其間變更完全移除(接近 svn revert),內容及狀態皆是上一版 |
取得檔案變更應使用 git checkout
而非濫用 git reset
git reset -p
: 互動式選擇還原區塊
git reset --hard ORIG_HEAD
: 復原重大變更的前一版git reflog
git gc
之前都存在的特性,將因 reset 而沒有指向的 commit 調出來
reflog
列出來的內容是做完指令的結果,所以要還原必須再往前找一版commit --amend
--reset-author
--author=<author>
:git commit --amend --author="Author Name <email@address.com>" --no-edit
-a
)、HEAD 都是一種指向 commit 的指標(以文字檔案型式儲存著 commit id)git checkout --orphan <branch_name>
git branch --move [<oldbranch>] <newbranch>
.git/refs/heads/<oldbranch>
分支git merge --ff
(default)=> 快轉 (Fast Forward):快速合併,直接使用每一次異動的 commit,最好使用在同一分支的情況下,ex. 本地 merge 遠端
git merge --no-ff
=> No Fast Forward:將多個異動併為一個 commit
git merge --ff
vs. git merge --ff-only
--ff
:預設行為,若不行使用 Fast Forward 則用自動轉為 No Fast Forward--ff-only
:明確要求必須使用 Fast Forward,若不能使用 Fast Forward 時則拒絕操作git pull
== git fetch
+ git merge
git push
git pull --rebase
git pull --rebase --autostash
無法 Fast Forward 的情形,本地端與遠端版本已經不是同一條分支了
git cherry-pick <commit_id>
git rebase
(等同於 reset 後再做 cherry-pick)git merge --allow-unrelated-histories <orphan_branch_name>
合併孤兒分支--no-ff
vs. --no-ff --no-commit
vs. --squash
--squash
and --no-ff --no-commit
?--no-commit
:套用合併內容而不直接 commit,待使用者自行 commit
--no-ff
產生的 merge commit 上不會有 diff 資訊,要自行到被併入的 branch 中查看各個 commit--no-ff
(master) $ git merge --no-ff topic
--no-ff --no-commit
--squash
git [merge | rebase] [-X ours | theirs] <commit>
-X ours
:以目前 head 所在的 branch 為主-X theirs
:以不是 head 所在的 branch 為主git checkout [--ours | theirs]
(dev)$ git merge master
:dev <- current(在 dev 上建立 merge commit 將 master 內容 merge 至 dev,會把 merge commit 的另一個 parent 指向 master)(dev)$ git rebase master
:master <- current(將 dev 上的 commit 一個一個重新 commit 到 master,head 指向 master 且會一個一個移動到後方重新 commit 的新 commit)git branch --merged
git branch --merged | egrep -v "(^\*|master|dev)" | xargs git branch -d
git branch --no-merged
git rebase 的重新 commit 為:
https://blog.yorkxin.org/2011/07/29/git-rebase
git rebase master
checkout
到指定 commitcherry-pick
到一個沒有 branch 指向的 commitcheckout
回自己 commit 後 reset
回沒有名字的 branchgit rebase --autostash
git rebase --skip
git rebase -i
git rebase -i <base_commit_id>
(可修改 base commit 後的 commit)
--squash=<commit>
標註要壓縮哪個版本git rebase -i --autosquash
會自動將修正版本接在 commit 版本之後並設為 squash--fixup=<commit>
標註要修正哪個版本 (效果同 squash)git add <file>
標註衝突已解決,並使用 git rebase --conitnue
完成 (而不是增加額外的commit)git rebase -i --root
git rebase --onto
git rebase --onto <new base-commit> <current base-commit> <target-branchName>
git rebase --onto <new base-commit> <current base-commit>
(rebase 目前的分支)git cherry-pick
--no-commit
:先不 commit,可利用此參數來多次 cherry-pick 不同的 commit 內容
git cherry-pick --abort
來中斷 cherry-pickgit cherry-pick
多個 commitgit cherry-pick commit1 commit2
git cherry-pick preStartCommit..endCommit
或 git cherry-pick startCommit^..endCommit
preStartCommit..endCommit
代表從 preStartCommit
(不包含此 commit 之異動內容)到 endCommit
為止的所有 commitstartCommit^..endCommit
代表從 startCommit
(包含此 commit 之異動內容)到 endCommit
為止的所有 commitgit cherry-pick parentBranchName..targetBranchName
git revert <commit_id>
HEAD^^
(^
為跳脫字元 Escape Characters)https://gitbook.tw/chapters/branch/how-git-know-what-current-branch-is.html
當你在做一些比較「危險」的操作(例如像
merge
、rebase
或reset
之類的),Git 就會把 HEAD 的狀態存放在這裡,讓你隨時可以跳回危險動作之前的狀態
git reset
全部 Staged -> Unstaged,可搭配 hard
、soft
、mixed
等參數
git reset [--] <file>
Staged -> Unstaged
--
:代表將 --
後方的每個參數皆一率視為檔案路徑
git reset <commitCode>
會 checkout 至指定 commit,並將差異還原成 Unstaged
一樣可搭配 hard、soft、mixed 等參數
但要小心每一個參數處理差異的方式並不同
git checkout <file>
Staged 中有記錄:以 Staged 來還原
Staged 中沒有記錄:以目前 commit 來還原,Unstaged 內容會消失
git clean
git clean -n
只列出將會清除的清單(Dry run, 不搭配其他參數則列出 non-ignored 的 untracked 檔案)git clean -f
執行清除檔案(不搭配其他參數則清除 non-ignored 的 untracked 檔案)git clean -X
要清除 untracked 檔案(ignored files)git clean -x
要清除所有 untracked 檔案(ignored and non-ignored files)git clean -d
要同時清除 untracked 目錄git diff
git diff HEAD
git diff <commit>
git diff --cached <HEAD>
(HEAD 可省略)git diff --cached <commit>
git diff <src-commit> <target-commit>
git diff --binary
git diff --name-only
: 僅列出工作目錄與索引間異動的檔案git diff --name-status
: 列出工作目錄與索引間異動的檔案及狀態git diff --name-status <src-commit> <target-commit>
: 列出兩版本間異動的檔案及狀態
--diff-filter
指定特定狀態,配合 shell script 自動修正佈署環境檔案https://juejin.im/post/5b5851976fb9a04f844ad0f4
git diff <src-commit> <target-commit> > my-patch.patch
--binary
git apply my-patch.patch
git apply --check
檢查套用 patch 過程是否會發生衝突git apply <patch_file>
git apply --reverse <patch_file>
format-patch
vs. diff >
https://yodalee.blogspot.com/2017/03/git-patch.html
常見的 diff 其實也就是git diff 生成的 patch,內容就是:這幾行刪掉,這幾行加上去,用 git diff > commit1.patch 就能輕鬆生成。git patch system 則是用 git format-patch 來產生,它提供比 diff 更豐富的資訊
git stash show
git stash pop <n>
:n 是離現在最近的第幾個 stash(0-base)https://zlargon.gitbooks.io/git-tutorial/content/advanced/add_checkout_part_of_file.html
git config --local core.ignorecase false
將 git 設定為大小寫敏感git mv client/themeCore/components/core/productCard temp
git mv temp client/themeCore/components/core/ProductCard
git remote
--verbose
git remote add upstream https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git
git pull --rebase
git rebase --abort
再說git push [<遠端倉庫名稱>] [<本地分支名稱>][:<遠端分支名稱>]
git push origin local-name
git push origin local-name:remote-name
git push --force
git push --force-with-lease
git branch -u <遠端倉庫名稱>[/<遠端分支名稱>] [<本地分支名稱>]
== git branch --set-upstream-to=<遠端倉庫名稱>[/<遠端分支名稱>] [本地分支名稱]
git checkout -b [<本地分支名稱>] --track <遠端倉庫名稱>[/<遠端分支名稱>]
git checkout <分支名稱>
的預設行為之一(如果有同名的遠端分支名稱)git push -u <遠端倉庫名稱> <本地分支名稱>
== git push --set-upstream <遠端倉庫名稱> <本地分支名稱>
git branch -u <遠端倉庫名稱>[/<遠端分支名稱>] [<本地分支名稱>]
git push origin --delete <branchName>
git fetch --prune
刪掉遠端分支git branch -r
列出遠端追蹤分支git branch --delete --remotes origin/<branchName>
git tag <tag_name> <commit>
git tag -d <tag_name>
.git/refs/tags/<tag_name>
git tag -a <tag_name> <commit>
tag -n
顯示 tag 訊息)git tag -d <tag_name>
git push --tags
git push --delete origin <tag_name>
git fetch
git fetch --prune-tags
git checkout <tag_name>
: 實際上是把標籤指向的版本取出 (因為標籤不是分支,所以會跑去 detached HEAD)
-b
同時建立分支, ex git checout -b hotfix/6.0.1 6.0.1
https://blog.chh.tw/posts/git-submodule/
git remote set-url --push origin <URL_TO_MY_REPO>
設定git log --oneline --graph -n
--oneline
: 僅顯示第一行訊息,即 commit log--graph
: 以線圖呈現-n
: 最近幾版