Git是什么?代碼管理工具栓撞。Git是怎么實(shí)現(xiàn)的遍膜?我們不需要關(guān)心。我們只要把目光盯著每個(gè)commit瓤湘,知道git的每個(gè)命令都是為此服務(wù)的瓢颅,足矣。
正如我在模型里形容的弛说,git的每個(gè)分支都可以理解為一根竹子挽懦,而每個(gè)commit就是竹子的一節(jié),這就是我們需要的全部信息剃浇。merge巾兆、rebase、cherry-pick就是維護(hù)和改造commit的三把利器虎囚。
merge就是從兩根竹子的根部角塑,一節(jié)節(jié)向上對比它們的不同,當(dāng)有不同發(fā)生時(shí)淘讥,有兩條路走就兩條路都保留圃伶,并用一個(gè)新的節(jié)點(diǎn)糅合起來,只有一條路就直接走過去,當(dāng)然兩條路可能有沖突窒朋,解決一下就好了搀罢。
rebase也同樣是從兩根竹子的根部出發(fā),只不過當(dāng)遇到不同時(shí)侥猩,就把你的這條路多出的部分剪掉榔至,先把別人的放進(jìn)來,再一節(jié)一節(jié)安回去欺劳,因?yàn)槊恳还?jié)都重新安唧取,所以commitId都會變,而且每一節(jié)都有可能產(chǎn)生沖突划提,理論上最糟糕的情況是有多少節(jié)竹子要安枫弟,就得解決多少次沖突。所以務(wù)必勤快些鹏往,隨時(shí)隨地git pull --rebase
淡诗。
cherry-pick就簡單了,不需要從竹子根部出發(fā)伊履,只取需要的commit就行韩容,它像是rebase的后半段,也有可能產(chǎn)生一堆沖突湾碎。宙攻。
除了merge的Non Fast Forward(非快進(jìn)式合并),其他的所有方式都會丟失操作記錄介褥,所以一定要牢記自己的關(guān)注點(diǎn)是操作記錄還是整潔。
還有一個(gè)概念需要了解一下递惋,HEAD和FETCH_HEAD柔滔。HEAD就是頭節(jié)點(diǎn),是一個(gè)指針萍虽,也就是始終指向竹子最上一節(jié)睛廊。FETCH_HEAD是當(dāng)你執(zhí)行 git fetch 時(shí),拉取下來的代碼的頭結(jié)點(diǎn)杉编。
只要真的把每個(gè)分支都想象成一根竹子超全,記得我上邊說的區(qū)別,把自己當(dāng)成git邓馒,你在操作git時(shí)就能游刃有余嘶朱,遇到的大多數(shù)問題都有把握搞定,而不至于被git整的焦頭爛額光酣。大多數(shù)人遇到問題往往就是因?yàn)閷it的理念不熟悉疏遏,不了解每條命令的目的造成的。包括之前的我也是,經(jīng)常忙碌到最后财异,發(fā)現(xiàn)自己渴求的不過是回到最開始的狀態(tài)倘零,好給自己一次重新來過的機(jī)會。戳寸。
以下是我在平時(shí)會使用到的一些命令的總結(jié)呈驶,希望能夠?qū)Υ蠹矣兴鶐椭?/p>
初始化相關(guān)
// 初始化一個(gè)倉庫
git init [project name]
// clone一個(gè)已有的倉庫
git clone [url]
config相關(guān)
// 設(shè)置用戶名
git config [--global] user.name "Your user name"
// 設(shè)置郵箱
git config [--global] user.email "Your user email"
// 配置縮寫,例如此處 git status 就可以簡寫成 git st
git config [--global] alias.st "status"
// 查看配置列表
git config [--global] --list
// 編輯配置列表
git config [--global] --edit
commit相關(guān)
// 查看工作區(qū)改動
git status
// 添加一個(gè)文件
git add [file]
// 添加所有文件
git add .
// 創(chuàng)建一個(gè)commit
git commit -m "commit message"
// 檢查工作區(qū)和暫存區(qū)之間的區(qū)別疫鹊,如果跟上文件俐东,就是只看當(dāng)前文件的區(qū)別
git diff [file]
// 檢查暫存區(qū)和版本庫之間的區(qū)別
git diff --staged [file]
// 檢查工作區(qū)和版本庫之間的區(qū)別
git diff HEAD
// 將文件從暫存區(qū)去除,回到工作區(qū)
git reset [file]
// 將工作區(qū)的更改去除
git checkout -- [file]
// 回到某個(gè)commit订晌,不加--hard回完之后更改的文件會進(jìn)到工作區(qū)虏辫,加上--hard這些文件就不見了
// HEAD~1 表示第二新的commit,如果是HEAD~1锈拨,可以簡寫成HEAD~ 這里也可以跟上具體的commitId
git reset [--hard] HEAD~1
暫存未完成的工作
// 暫存工作區(qū)的內(nèi)容砌庄,前提是文件已經(jīng)被追蹤了
// 不想寫message,可以簡單使用 git stash
git stash save [save message]
// 查看stash列表
git stash list
// 彈出暫存的工作奕枢,會從暫存里刪除
git stash pop
// 只把stash里的內(nèi)容取出來娄昆,但不彈出
git stash apply stash@{0}
// 刪除某個(gè)stash
git stash drop stash@{0}
提交歷史相關(guān)
// oneline 表示只顯示一行,raw可以查看樹的結(jié)構(gòu)缝彬,還有其他可以配置的
// --abbrev-commit 可以顯示簡短的commitId
// --author 只顯示該作者的
git log --pretty=[oneline, raw, ...] --abbrev-commit --author=[author name]
// 查看提交的點(diǎn)線圖
git log --graph
// 查看dev有萌焰,master沒有的commit
git log dev ^master
// 查看 dev 中比 master 中多提交了哪些內(nèi)容
git log master..dev
// 查看兩個(gè)分支的區(qū)別,包含 < 是master的谷浅,包含 > 是dev的
git log --left-right master...dev
// 顯示一次commit的內(nèi)容
git show [commitId]
// 顯示一個(gè)文件的修改歷史
git log --follow [file]
// 顯示一個(gè)文件的修改歷史扒俯,和具體修改內(nèi)容
git log -p [file]
// 顯示一個(gè)文件每一行的修改歷史
git blame [file]
分支相關(guān)
// 新建一個(gè)branch,如果跟上commitId一疯,則新建分支的HEAD將指向它
git branch [branch name] [commitId]
// 切換一個(gè)branch
git checkout [branch name]
// 新建一個(gè)branch并切換到它撼玄,如果跟上commitId,則新建分支的HEAD將指向它
git checkout -b [branch name] [commitId]
// 刪除一個(gè)分支墩邀,如果是-D表示強(qiáng)制刪除
git branch -d|-D [branch name]
// 檢查兩個(gè)branch之間的差別
git diff [branch1]..[branch2]
// 檢查兩個(gè)branch共有父節(jié)點(diǎn)和branch2的差別
git diff [branch1]...[branch2]
merge相關(guān)
// 合并某個(gè)分支到當(dāng)前分支 可選的--no-ff 表示不允許快進(jìn)
git merge [branch name] --no-ff
// 回退一次merge掌猛,commitId在哪條路就回到哪條路
git reset --merge [commitId]
// 中斷一次merge,相當(dāng)于回到merge前眉睹,必須在merging狀態(tài)使用
git merge --abort
cherry-pick相關(guān)
// 將某個(gè)commit摘取過來
git cherry-pick [commitId]
// 摘取(commitId1, commitId2]之間的commit
git cherry-pick [commitId1]..[commitId2]
// 當(dāng)出現(xiàn)沖突后荔茬,解決完沖突,并執(zhí)行 git add竹海,之后執(zhí)行--continue就可以
git cherry-pick --continue
// 放棄一次cherry-pick
git cherry-pick --abort
rebase相關(guān)
// 拉取origin master的代碼慕蔚,并進(jìn)行rebase
git pull --rebase origin master
// 和cherry-pick類似,解決完沖突后執(zhí)行
git rebase --continue
// 放棄一次rebase
git rebase --abort
// 交互式地修改從(commitId|HEAD~n, HEAD]之間的每個(gè)commit
git rebase -i HEAD~n | [commitId]
reflog
// 非常強(qiáng)大的功能站削,記錄了你每次干了什么坊萝,確保任何時(shí)候都可以進(jìn)行回退
git reflog
最后演示一下 git rebase -i
和 git reflog
的作用。輸入 git rebase -i HEAD~
會打開以下頁面:
在選中范圍內(nèi)的commit會依次列出,前面有一個(gè) pick 單詞十偶,替換這個(gè)單詞為提示中的某一個(gè)就可以進(jìn)行變更菩鲜。例如改為 r 或者 reword,表示只修改commit message惦积,保存之后git會再次彈出一個(gè)框接校,就可以修改對應(yīng)的commit message了。
git reflog記錄的是你的操作記錄狮崩,而不是commit記錄蛛勉,這點(diǎn)一定要分清。以下就是一個(gè)示例:
這時(shí)候睦柴,你想回到哪一步诽凌,直接 git reset --hard [commitId]
就可以了,這是git為你提供的一份超級后悔藥坦敌,請合理食用哦侣诵。
本文的分享到此就結(jié)束了,git還有很多五彩斑斕的命令狱窘,但是本文目的不在于把git的每個(gè)命令都介紹給你杜顺,遇到特定問題查一下資料就可以做到。我們是希望你能夠理解git的主要目的蘸炸,時(shí)刻謹(jǐn)記自己在操作哪根竹子躬络,關(guān)注哪個(gè)竹節(jié),不要陷于無窮無盡的命令中無法自拔搭儒,讓git成為提高工作效率的利器穷当,而不是你前進(jìn)道路上的絆腳石。git的好處仗嗦,使用越久就會越有體會膘滨,希望git能夠陪伴你成長,記錄你進(jìn)步的旅途稀拐。
附一張高清的圖片總結(jié),你可以通過掃碼關(guān)注微信獲取PDF版哦~
我是飛機(jī)醬丹弱,如果您喜歡我的文章德撬,可以關(guān)注我~
編程之路,道阻且長躲胳。唯蜓洪,路漫漫其修遠(yuǎn)兮,吾將上下而求索坯苹。