工做中必備 git 技能詳解
絕大多數人對於 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 有什麼區別?- git如何合併兩個補丁,對第三個補丁進行修改?(這個很重要,由於你不會才致使 git commit 的信息沒有意義,commit 不夠小和多)
又或者,你試過合併commit 嗎?commit message 寫的很差時如何修改?如何改變 commit 的順序?
若是以上有不清楚的話,那麼我但願如下的文章對你有幫助。
你所不知道的 github 初始化
初始建立一個 github 倉庫時,github 會給一些命令你去建立 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 merge gakki/master feat-add-lister //把 gakki 的 master 分支 merge 到 feat-add-lister
由於 pull 的時候, 當出現衝突而你解決掉後,會有多餘的merge
信息(commit message),因此我是推薦在本身的分支開發時,使用git fetch gakki
以及 git rebase gakki/master feat-add-lister
(不會出現多餘信息,處理衝突更加自由)
合併你的 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(棧)實現,因此能夠 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 就能夠了。
【對錯誤commit-message的撤銷】
git commit -a -m 'OK'
git commit -a -m "M 一、諮詢頁富文本-html標籤;";git push origin master:master
modify a.file
git commit -a -m 'OK' 錯誤操做
git commit -a -m "M 一、諮詢頁富文本-html標籤;";git push origin master:master 【查出該次的commitId 】
git log 查到commitId,【4b8b4e108943c0c12d31f8b0cc0b6a5eed49c0d7】
git commit -a -m 'OK'
git commit -a -m "M 一、雲新聞地名、業務名數據遷出到數據集文件,便於集中管理和後續維護;";git push origin master:master
$ git reset 4b8b4e108943c0c12d31f8b0cc0b6a5eed49c0d7
Unstaged changes after reset:
M README.md
M src/api/teamDataset.js
M src/pages/cloundNews.vue
M src/pages/newsWebView.vue
git commit -a -m '3NewFile'