博客可能樣式更好看: http://yonghaowu.github.io/2017/06/18/TheGitYouShouldKnow/
歡迎大家的意見匾旭,謝謝:P
絕大多數人對于 git的認識只停留在git status
, git add
, git push
, git pull
, 好一點會知道git merge
, 那就是全部了美浦。
不信?
試試你能回答出以下問題不:
-
git push origin master
命令中喳挑,origin 代表的是什么,整個命令是什么意思滔悉,origin 可以修改不 -
git fetch origin; git rebase origin master
這些命令知道嗎伊诵?跟 merge 有什么區(qū)別? - git如何合并兩個補丁回官,對第三個補丁進行修改曹宴?(這個很重要,因為你不會才導致 git commit 的信息沒有意義歉提,commit 不夠小和多)
又或者笛坦,你試過合并commit 嗎?commit message 寫的不好時如何修改唯袄?如何改變 commit 的順序弯屈?
如果以上有不清楚的話,那么我希望以下的文章對你有幫助恋拷。
你所不知道的 github 初始化
初始創(chuàng)建一個 github 倉庫時资厉,github 會給一些命令你去創(chuàng)建 git本地項目,git init
就不用說了蔬顾,git remote add origin git@github.com:YongHaoWu/test.git
你知道這里的 origin 是什么嗎宴偿?
是的,就僅僅是一個名字诀豁,對git@github.com:YongHaoWu/test.git
這個 ssh 地址的命名窄刘,你可以把 origin
命名為 gakki
—— git remote add gakki git@github.com:YongHaoWu/test.git
, 以后就可以用git push gakki master
了。
另外舷胜,你還可以 add
好幾個名字娩践,比如:你在 github 跟coding 同樣都有倉庫放代碼的情況。
git push -u origin master
, 這里就是把 master(默認 git 分支)推送到 origin, -u
也就是--set-upstream
, 代表的是更新?默認推送的地方翻伺,這里就是默認以后git pull
和git push
時材泄,都是推送和拉自 origin 。
令 commit 更漂亮
對于 git 工作流吨岭,我認為commit 數要多而有意義拉宗,branch 也要多而有意義——也就是,一個小功能就要開一個分支辣辫,一個分支里要有一些有意義的 commit旦事。 好處就是沖突會很少,review 代碼速度加快急灭,commit 都是有意義的姐浮,而且利于回退。
要做到這些化戳,離不開掌握git rebase
永遠使用 rebase
git rebase
Reapply commits from one branch on top of another branch.
Commonly used to "move" an entire branch to another base, creating copies of the commits in the new location.
相信你可以理解以上的英文:把 A 分支rebase 到 B 分支单料,也就是把 A 的 commit 與 B 的合并,并且保留 B 獨特的 commit点楼。
還是很抽象,對吧白对?
看一個例子:git pull gakki feat-add-listener
這里就是把 gakki
倉庫拉到 feat-add-listerner
分支掠廓。實際上,所做的東西等價于:
git fetch gakki //把 gakki 倉庫的東西都拉下來本地
git rebase gakki/origin feat-add-lister //把 gakki 的 master 分支 rebase 到 feat-add-lister
因為 pull 的時候甩恼, 當出現(xiàn)沖突而你解決掉后蟀瞧,會有多余的merge
信息(commit message),所以我是推薦在自己的分支開發(fā)時条摸,永遠使用 fetch悦污,rebase(不會出現(xiàn)多余信息,處理沖突更加自由)
合并你的 commits
Author: YongHao Hu <hyh@vincross.com>
Date: Fri Dec 23 17:55:49 2016 +0800
install skill: Fix skill pkg relative path.
commit 37f37e46a2570c0989a46f39169bba510ebdabd8
Author: YongHao Hu <hyh@vincross.com>
Date: Fri Dec 23 10:51:09 2016 +0800
mind: Add comments for understanding.
commit 4eb9b9743d2bdc301a0e97f73d652f67adc82b32
Author: YongHao Hu <hyh@vincross.com>
Date: Thu Dec 22 15:00:02 2016 +0800
skill-third-party: Add default include library.
假設你又以上三個 commit钉蒲,如何合并切端,修改呢?
git rebase -i HEAD~4
對前四個補丁就行修改顷啼,就會進入以下界面:
pick 0194373 skill-third-party: Change PKG_CONFIG_PATH and LD_LIBRARY_PATH.
pick 4eb9b97 skill-third-party: Add default include library.
pick 37f37e4 mind: Add comments for understanding.
pick 84c413a install skill: Fix skill pkg relative path.
# Rebase 986e234..84c413a onto 986e234 (4 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
有以下常用操作:
- 默認pick踏枣, 不做更改
- reword:改 commit message
- squash:當前補丁跟上一個補丁合并
- fixup: 跟 squash 作用一樣,但是會丟棄當前 commit 信息钙蒙,使用上一個的茵瀑;squash 則是可以讓你重新寫
需要修改時,把上面四個補丁最前面的 pick 改成對應操作(如 reword躬厌,fixup)马昨,然后保存退出即可。
不用擔心的回退
回退大家應該都知道git reset --hard commitID
, 把整個 git 回退到這個 commitID 里;
其實除了--hard
, 還有 soft
.
hard
是把改動全部都丟棄鸿捧,而soft
則柔軟一些屹篓,僅僅是把所做的 commit 丟掉,而改動都保留在本地——通常用來修改笛谦,再重新 commit 一遍抱虐。
做了胡亂的更改,導致 git log
都不正常饥脑,找不回那個 commit 了怎么辦恳邀?
不用擔心, 還有 git reflog
— Reference logs, or "reflogs", record when the tips of branches and other references were updated in the local repository.
用它可以看到你對當前項目所做過的所有 git 操作灶轰,所有 git 操作的 id 號——意味著你可以回退到任意的時刻谣沸。
所以,只要你沒有把改動沒有做 commit 就丟失笋颤,又或者用git push -f
把 github 倉庫覆蓋了乳附,你就可以恢復任意時刻的東西。
git stash 暫存更改
時刻要注意伴澄,當前修改沒有 commit 的時候赋除,不能 checkout 切換分支。
此時不想 commit非凌,便需要 git stash
暫存更改举农;顧名思義,stash 使用 stack(棧)實現(xiàn)敞嗡,所以可以 git stash
存多次颁糟,然后切換分支后, git stash pop
撤出來
比 grep 更好用的 git grep
相比于 grep -R keyword ./
, 我是更喜歡用 git grep keyword
, 差不多是一樣的喉悴,不過git grep
只是會找當前的 目錄中git 有 track(跟蹤)的文件【也就是變動時棱貌,git status 會檢測到變化的文件】
超級進階:分割commit
commit 03bb9a14f5ea00d51d2edc14587b37b1ab9ccf5d
Author: YongHao Hu christopherwuy@gmail.com
Date: Fri Jul 10 17:23:02 2015 +0800
msvcp110: Add tr2_sys__Unlink implementation and test.
commit 24137cd93c783ced61ca152cb4384287e6859ba4
Author: YongHao Hu christopherwuy@gmail.com
Date: Tue Jul 7 11:04:25 2015 +0800
msvcp110: Add tr2_sys__Symlink implementation and test.
commit 51702048d9ecd1dc3887a63c057761a8547ce5f6
Author: YongHao Hu christopherwuy@gmail.com
Date: Thu Jul 2 23:23:51 2015 +0800
msvcp110: Add tr2_sys__Link implementation and test.
假設我們想要分割 msvcp110: Add tr2_sys__Unlink implementation and test. 這個 commit,可以直接使用
git rebase -i HEAD~7(數字隨意箕肃,反正在 Unlink 這個 commit 前就可以了)婚脱,選擇 Unlink 這個 commit,
改成 edit突雪。
一般情況下起惕,就是這樣修改 commit 的,修改后再 git rebase –continue.
但是咏删,我們需要的是分割補度窍搿:
選擇 git rebase HEAD^, 撤銷這次 commit,再把想改動的文件 git add, 再 git commit, 這樣就可以分割很多補丁督函。
最后嘀粱,git rebase –continue 就可以了激挪。