十分钟了解 git 那些 “不常用” 命令
??點擊上方?好好學java?,選擇?星標?公眾號
重磅資訊、干貨,第一時間送達 今日推薦:Java實現QQ登錄和微博登錄個人原創+1博客:點擊前往,查看更多 鏈接:https://segmentfault.com/a/1190000022107836本文主要是介紹git不常用初期不太會用的命令,希望你看了能理解這些命令的使用,并在平時使用過程中一點點地刻意進行練習,逐步熟練并知道何時需要用到這些命令去解決你的問題。( 我也在不斷熟練中:D
基礎命令
如果你還是剛剛接觸git命令,還不清楚 倉庫 、工作流、分支、提交 的童鞋可以先看下 git使用簡易指南,這個應該是我初學git看的第一份且收藏至今的指南了~ 圖解很清晰易懂,真10分鐘入門的資料:D
然后你會發現如下基礎命令將會成為你之后幾乎每天都要用到的80%的命令:
git clone git@github.com:nohosts/nohost.git 克隆遠程倉庫的內容到本地
git pull origin master 獲取遠程分支master并merge到當前分支
git branch -a 查看全部分支(遠程+本地)
git checkout -b bugFix新建bugFix,并切換到到此分支。(如果分支已存在則去掉-b即可)
git status 查看當前~~~~版本狀態(是否修改)
git add . 增加當前子目錄~~~~下所有文件更改至暫存區
git commit -m 'xxx' 提交暫存區的修改至本地的版本庫, 修改備注為xxx
git push 將本地版本推送到遠程分支
git tag v1.0 dfb02e6e4f2f7b573337763e5c0013802e392818 增加v1.0的tag到某個提交上
git merge testBranch 合并testBranch分支至當前分支`
git stash 暫存本地的當前修改,將本地代碼重置為HEAD狀態。(如果需要取出修改,命令后加一個pop即可)
git log 顯示提交日志(如果想每個提交信息顯示在一行,可以加上--pretty=oneline)
git show dfb02e6e4f2f7b573337763e5c0013802e392818顯示某個提交的詳細內容
git reset --hard HEAD 將當前版本重置為HEAD
注意這兩個命令的區別:
git pull = fetch + mergegit pull --rebase = fetch + rebase“不常用”命令
一、git rebase 變基
在 Git 中整合來自不同分支的修改主要有兩種方法:merge 以及 rebase。在本節中我們將學習什么是“變基”,怎樣使用“變基”,并將展示該操作的驚艷之處,以及指出在何種情況下你應避免使用它。——[git-scm變基]:https://git-scm.com/book/zh/v2/Git-%E5%88%86%E6%94%AF-%E5%8F%98%E5%9F%BA
說明:后面的舉例每個 分支 都有不同的顏色,*前綴 表示現在所處的分支,而 commitid 都由C0、C1、C2代替每一個提交的哈希值,箭頭 表示分支的繼承
我們之前整合分支用的最多的就是merge了,那merge和rebase有什么區別呢?
1. merge
★merge 合并兩個分支時會產生一個特殊的提交記錄,它有兩個父節點。簡單說就是:“我要把這兩個父節點本身及它們所有的祖先都包含進來。”
”git checkout master; git merge bugFix下圖中左、右兩張圖分別是執行如下代碼前后的樣子:
merge-1可以看出來,紅色圈圈是最主要的改變—— merge 合并分支后,會在master分支上 新增一個C4提交 ,而C4提交里面有master和bugFix代碼庫所有的修改。
此時的bugFix代碼還沒和master 同步(顏色不同),我們還需要執行如下代碼:
git checkout bugFix; git merge master merge-22. rebase
★rebase 實際上就是取出一系列的提交記錄,“復制”它們,然后在另外一個地方逐個的放下去。它的優勢就是可以創造更線性的提交歷史。
”git checkout bugFix; git rebase master下圖中左、右兩張圖分別是執行代碼前后的樣子:
變基-1bugFix 分支里的內容通過 rebase 直接 復制 到 master 分支上。現在 bugFix 分支上的工作在 master 的最頂端,同時我們也得到了一個更 線性 的提交序列。
注意:提交記錄 C3 依然存在(樹上那個半透明的節點),而 C3' 是我們 rebase 到 master 分支上的 C3 的 副本(內容是一樣的,只是commitid更新了)。
但是,此時master還沒有和bugFix 同步(顏色不同),我們還需要執行如下代碼:
git checkout master; git rebase bugFix 變基-2.png由于bugFix繼承自master,所以 Git 只是簡單的把master分支的引用向前移動了一下而已。
3. rebase的延伸用法
3.1 省去切換分支即可rebase
git rebase targetBranch originBranch表示切換到originBranch,然后執行git rebase targetBranch
3.2 修改某幾次提交
git rebase -i commitid如上圖標注的,傳的commitid為你想修改的提交的 前一個commitid。執行命令后進入vi模式,會提示你一些操作命令(p、r、e...)你只需要在最上方修改默認的pick為你想要的操作,然后退出并wq保存即可生效。
具體操作:
pick 使用(啥也沒變)
reword 使用并修改commit msg, 改后commit id也會更新
edit 使用并編輯commit時的文件 編輯后git add . 然后git commit —amend還可以更新最新的commit msg。git rebase —continue 把后面的內容加進來并解決沖突, 最后提交。最新的commit id也更新
squash 合并commit 選擇最新的commit去合并,然后continue發現這一次和上一次的commit msg都有,你可以刪除只留下想要的也可以進行修改 然后 continue和push。如果你不刪的話會發現全部文本行都組成了一個多行的commit msg 如果commit再往前已經沒有了 就不能再squash,否則會報錯( error: cannot 'squash' without a previous commit )。然后 git rebase --edit-todo 可以繼續vi編輯
fixup 合并commit到前面而且commit,commit msg也沒了
drop 刪除某個commit
注意:如果想要恢復這一次rebase操作,則可以執行 git rebase —abort。如果想完全恢復本地分支到遠程的狀態,可以執行 git reset --hard origin/bugFix ,或者你可以 git reflog 找到對應提交記錄回滾,但是有點麻煩
4. rebase需要謹慎使用
當你要改寫的commit history還沒有被提交到遠倉庫的時候,也就是說,還沒有與他人共享之前,commit history是你私人所有的,那么想怎么改寫都可以。
而一旦被提交到遠程后,這時如果再改寫history,那么勢必和他人的history長的就不一樣了。git push 的時候,git會比較commit history,如果不一致,commit動作會被拒絕,唯一的辦法就是帶上 -f 參數,強制要求commit,這時git會以committer的history覆寫遠程分支,從而完成代碼的提交。雖然代碼提交上去了,但是這樣可能會造成別人工作成果的丟失,所以使用 -f 參數要慎重。
所以,在不用 -f 的前提下,想維持樹的整潔,方法就是:在 git push 之前,先 git fetch,再 git rebase。
4. 總結
無論是通過變基,還是通過三方合并,整合的最終結果所指向的快照始終是一樣的,只不過提交歷史不同罷了。變基是將一系列提交按照原有次序依次應用到另一分支上,而合并是把最終結果合在一起。
在你自己的分支(非他人共享)的分支進行rebase是可以的,但是如果在公共分支rebase修改提交需要謹慎——最好是先 fetch、再 rebase、最后 push。
二、git cherry-pick 選擇
★cherry-pick 可以將提交樹上任何地方的提交記錄取過來追加到 HEAD 上(只要不是 HEAD 上游的提交就沒問題)。`
”git checkout master; git cherry-pick C2下圖中左、右兩張圖分別是執行代碼前后的樣子:是不是有點眼熟:D 沒錯 這個和rebase的效果蠻像的,這兩個命令都可以實現復制提交~
cherry-pick.png三、git reset VS revert 回滾
★git revert HEAD是用一次新的commit來回滾之前的commit,git reset 是直接向上移動分支,刪除一些commit看上去像從未提交一樣。這兩者看似達到的效果是一樣的,其實完全不同。
”git reset HEAD~1 git revert HEAD如下所見,圖1是初始狀態(需要撤回 C2 提交),圖2和3 是從圖1分別執行 reset 和 revert 后的結果:
reset執行后,master 分支移回到了 C1;現在我們的本地代碼庫根本就不知道有 C2 這個提交了
revert執行后,在我們要撤銷的提交記錄 C2 后面多了一個新提交C2',而C2'引入了更改—— 這些更改是用來撤銷C2這個提交的。也就是說C2'的狀態與C1是相同的。
注意:
如果你已經push到線上代碼庫, reset 刪除指定commit以后, 你git push可能導致很多沖突.但是revert 并不會。
如果此回退的分支合并主干分支時,reset 恢復部分的代碼依然會出現在歷史分支里,但是revert 方向提交的commit 并不會出現在歷史分支里。
四、HEAD^n 和 HEAD~n 相對引用
★HEAD 是一個對當前檢出記錄的符號引用 —— 也就是指向你正在其基礎上進行工作的提交記錄。HEAD 總是指向當前分支上最近一次提交記錄 (如果想看 HEAD 指向,可以通過 cat .git/HEAD 查看, 如果 HEAD 指向的是一個引用,還可以用 git symbolic-ref HEAD 查看它的指向。)
”1. 基礎使用:
使用 ^ 表示向上移動 1 個提交記錄。n表示第n個父提交,不填默認是1(正上方)
使用 ~<num> 向上移動多個提交記錄 如 ~3
注意:操作符還支持鏈式操,如HEAD^2~3^
2. 延伸用法:移動分支可以直接使用 -f 選項讓分支指向另一個提交。例如下面的命令會將 master 分支強制指向 HEAD 的第 3 級父提交。
git branch -f master HEAD~3這次主要就總結了這幾種“不常用”git命令,希望大家和我都可以多多練習,讓他變成你需要時就可以自如使用的“常用”命令!:D
墻裂推薦一個[可視化的git練習網站]:https://learngitbranching.js.org/,很易懂好用~
總結
以上是生活随笔為你收集整理的十分钟了解 git 那些 “不常用” 命令的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java SPI 源码解析及 demo
- 下一篇: JDK 13 的最新垃圾回收器ZGC,你