Git超實用總結,不再怕記憶力很差了

歡迎你們前往騰訊雲+社區,獲取更多騰訊海量技術實踐乾貨哦~javascript

本文由騰訊工蜂發表於雲+社區專欄java

Git 是什麼?

Git 是一個分佈式的代碼管理容器,本地和遠端都保有一份相同的代碼。 Git 倉庫主要是由是三部分組成:本地代碼,緩存區,提交歷史,這幾乎是全部操做的本質,可是爲了文章更加簡單易懂,就不圍繞這塊展開了,有興趣的能夠去了解下。 開門見山,咱們直接來講說 Git 有哪些常見的操做。git

Git 有哪些常規操做?

咱們簡單說說Git有哪些常規操做,可以讓咱們應付簡單的開發需求。github

克隆代碼

✦ 克隆遠端代碼緩存

git clone + 遠程庫地址
複製代碼

✦ 查看本地的代碼狀態安全

// 能夠明確的呈現出本地倉庫的狀態
// 哪些文件發生改動,哪些文件已經提交到本機
// 以及一些操做指示。
git status
複製代碼

img

✦ 同步遠端分支變化app

// 拉取指定分支的變化
git fetch origin master 
// 拉取全部分支的變化
git fetch 
// 拉取全部分支的變化,而且將遠端不存在的分支同步移除【推薦】
git fetch -p
複製代碼

✦ 同步遠端代碼變化。機器學習

// 都是先 git fetch,而後執行合併操做
// 不一樣的是,git pull 執行的是 git merge,git pull -r 執行的是git rebase
git pull origin master 
git pull -r origin master
複製代碼

關於 git merge 和 git rebase 各自的優劣,後文會詳細介紹。分佈式

這部分主要介紹了關於代碼克隆,同步遠端代碼變化的相關操做。接下來,咱們看看關於本地代碼的一些操做。工具

操做 commit

首先咱們要明確一個概念:就是每一個 commit 都是一份完整的代碼狀態,用一個 commitID 來惟一標誌。

img

從某個角度上來講,Git維護的就是一個commitID樹,分別保存着不一樣狀態下的代碼。 因此你對代碼的任何修改,最終都會反映到 commit 上面去。

✦ 新增 commit

// 添加文件到緩存區,而後提交到本地倉庫
git add files
git commit -m '提交備註'
複製代碼

✦ 撤銷 commit

// 會將提交記錄回滾,代碼不回滾
git reset b14bb52

// 會將提交記錄和代碼所有回滾
git reset --hard b14bb52

// 將部分代碼文件回滾
git checkout -- files
複製代碼

✦ 合併 commit 合併 commit,本質上合併兩份不一樣狀態下的代碼。

// Git 提供了兩種合併 commit 的方式
git merge master
git rebase master
複製代碼

那麼 git rebase 和 git merge 到底有什麼區別呢? merge是兩個分支處理衝突後,新增一個 commit 追加到master上。 rebase是將someFeature分支上的commit記錄追加到主分支上,值得注意的是,這個時候他的commit其實已經發生變化。

img

相對來講,git merge 處理衝突更直接,而git rebase 可以保證清晰的 commit 記錄。

合併 commit 的時候,一般會發生衝突。 能夠全局搜索特殊字符好比<<<,找到須要處理的代碼位置,而後認真分析應該保留哪一部分代碼。

img

在團隊協做的時候,分支是必不可少的。那麼應該如何對分支進行操做呢?

操做分支

所謂的分支其實就是一個指向 commitID 的指針,你能夠去.git/refs/heads裏去看看。

img

一般狀況下,咱們建議分支至少可以明確的標記功能名稱,若是能標記用戶就更好了,好比qixiu/feature

✦ 查看分支

img

能夠同時看到本地分支和遠端分支,配合上前文介紹的git fetch -p能夠第一時間查看到最新的分支信息。

✦ 新增本地分支 其實就是建立一個指針指向某一個 commitID。

// git branch qixiu/feature + git checkout qixiu/feature
// 從當前分支新增一個新的分支qixiu/feature
// 通常狀況下,咱們應該從master或者其餘穩定分支來新增分支
git checkout -b qixiu/feature // 新建分支
git checkout qixiu/feature // 切換分支
複製代碼

✦ 刪除本地分支 其實就是移除一個指向 commitID 的指針。

// 刪除本地分支,若是本地還有未合併的代碼,則不能刪除
git branch -d qixiu/feature
// 強制刪除本地分支
git branch -D qixiu/feature
複製代碼

✦ 新增遠端分支 一般狀況下,咱們是新建本地分支,而後更新到遠端的方式來新增一個遠端分支

git push origin qixiu/feature
複製代碼

✦ 刪除遠端分支 一樣,咱們也是經過更新到遠端的方式來刪除一個遠端分支

// 等同於git push origin -d qixiu/feaure
git push origin :qixiu/feature
複製代碼

簡單彙總一下

上面說的可能有些分散,這兒簡單總結一下有哪些常用的操做:

git status // 查看本地代碼狀態
git add files // 添加代碼到緩存區
git commit -m '提交內容的備註' // 提交代碼到本地倉庫
git checkout -b branchName // 不加-b就是普通切換分支
git fetch -p // 同步遠端分支狀態
git pull -r origin branchName // fetch遠端代碼到本地,而且以rebase的方式合併代碼
git push origin branchName // 更新本地代碼到遠端
複製代碼

以上幾條命令已經可以應付平常的操做,稍微複雜一些的場景後文會介紹

基於基本操做,在實際項目中,咱們應該怎麼利用 Git 實現協做呢?

Git 有哪些比較好的實踐?

Git 有一些成熟的開發流程,比較主流的有兩種:基於功能分支的開發流程GitFlow開發流程。 相對來時,我更推薦前者,若是是複雜的大型項目,推薦GitFlow開發流程。 接下來,簡單介紹下這兩種協做模式。

基於功能分支的協做模式

基於功能分支的開發流程其實就是一句話:用分支來承載功能開發,開發結束以後就合併到 master 分支。 他的優勢是可以保證master分支的整潔,同時還能讓分支代碼邏輯集中,也便於 CodeReview。

分支命名規範

推薦使用以下格式:ownerName/featureName。 這樣既便於知道分支覆蓋的功能,也便於找到分支的負責人。之後清理分支的時候也很方便。

開發流程

✦ 從 master 切出一個新分支

git checkout -b qixiu/newFeature
複製代碼

✦ 開發一些新功能,而後提交 建議較多頻次的提交代碼到本地倉庫,以便可以更靈活的保存或撤銷修改。 此外爲了保證提交日誌的清晰,建議備註清楚的註釋。

git status
git add files // 挑選須要提交的文件,或者所有提交
git commit -m '提交備註'
git push origin qixiu/newFeature
複製代碼

✦ 若是功能開發完成,能夠發起一個CodeReview流程 ✦ 若是代碼測試經過,合併到 master,而後準備上線

// 冗餘版 合併到 master
git checkout master 
git pull -r origin master
git checkout qixiu/newFeature
git rebase master // 處理衝突
git checkout master
git merge qixiu/newFeature
git push origin master

// 精簡版 合併到 master
git checkout qixiu/newFeature
git pull -r origin master // 將master的代碼更新下來,而且rebase處理衝突
git push origin master // 將本地代碼更新到遠端
複製代碼

有幾點須要注意: 不要在master合併代碼,保證master的可用性很重要。 確保在正確的分支執行正確的操做。 不管是處理衝突仍是更新遠端代碼,請保有敬畏之心。

到此,一個正常的基於功能分支的開發流程就完成了。接下來看看另一個開發流程。

GitFlow 開發流程

GitFlow 比前文講的基於功能分支的開發流程要複雜得多,它更適合大型的複雜項目。 它圍繞項目發佈流程定義了一個嚴格的分支模型,全部的開發流程都是圍繞這個嚴格的分支模型進行。 而這個模型約定了每一個分支的角色,以及他們如何溝通。

咱們先來看看 GitFlow 開發流程中幾個約定的分支,以及他們各自承擔的角色是怎麼樣的?

img

✦ Master分支:用於存放線上版本代碼,能夠方便的給代碼打版本號。 ✦ Develop分支:用於整合 Feature 分支。 ✦ Feature分支:某個功能的分支,從 Develop 分支切出,而且功能完成時又合併回 Develop 分支,不直接和 Master 分支交互。 ✦ Release分支:一般對應一個迭代。將一個版本的功能所有合併到 Develop 分支以後,從 Develop 切出一個 Release 分支。這個分支不在追加新需求,能夠完成 bug 修復、完善文檔等工做。務必記住,代碼發佈後,須要將其合併到 Master 分支,同時也要合併到 Develop 分支。 ✦ Hotfix分支:緊急修復的分支,是惟一能夠從 Master 切出的分支,一旦修復了能夠合併到 Master 分支和 Develop 分支。

從每一個分支的功能和約定能夠看出,它流程多約束多,對於小規模應用並不適合。 固然 GitFlow 有一些輔助工具 gitflow 能夠自動化的完成這些任務,對於大型項目也頗有幫助。

前面講了 Git 有哪些基本操做,而後介紹了兩個主流的工做流程。 接下來咱們看看 Git 有哪些特別的技巧值得一提。

Git 有哪些小技巧?

Git 操做除了基本的代碼管理功能,還有一些小技巧可以讓你眼前一亮。

git reflog,查看操做記錄

這個我必定要放在第一個介紹,由於它曾經數次解救了個人代碼

img

仔細看上圖,reflog 記錄了你全部的 git 命令操做,對於復原某些莫名其妙的場景或者回滾誤操做有極大的幫助。

試想一個場景:你使用 git reset --hard commitID 把本地開發代碼回滾到了一個以前的版本,並且尚未推到遠端,怎麼才能找回丟失的代碼呢? 你若是使用 git log 查看提交日誌,並不能找回丟棄的那些 commitID。 而 git reflog 卻詳細的記錄了你每一個操做的 commitID,能夠輕易的讓你復原當時的操做而且找回丟失的代碼。 固然,若是你丟失的代碼都沒有提交記錄,那麼恭喜你,你的代碼真的丟了。

壓縮提交記錄

這也是一個很實用的功能,前文提過,咱們在開發中的時候儘可能保持一個較高頻率的代碼提交,這樣能夠避免不當心代碼丟失。可是真正合並代碼的時候,咱們並不但願有太多冗餘的提交記錄,並且 rebase 合併代碼的時候,會把每一個 commit 都處理一下,有時候會形成冗餘的工做。 因此,壓縮日誌以後不經能讓 commit 記錄很是整潔,同時也便於使用 rebase 合併代碼。

那麼,如何壓縮commit記錄呢? ✦ 使用 git log 找到起始 commitID ✦ git reset commitID,切記不要用 --hard 參數 ✦ 從新 git add && git commitgit push -f origin branchName,由於會有衝突,因此須要強制覆蓋遠端分支,請務必謹慎。 ✦ 合併到 master 中,而後更新遠端 master。

此外還有兩種壓縮日誌的辦法: git commit --amend:追加 commit 到上一個 commit 上。 git rebase -i:經過交互式的 rebase,提供對分支 commit 的控制,從而能夠清理混亂的歷史。

img

從實際應用來講,三種日誌壓縮都很優秀,git reset 更簡單,git rebase -i 更細膩。

git rebase,合併代碼

前文簡單介紹了 git rebasegit merge 的區別,坦率講,他們各有優劣。 git rebase 能讓你的 commit 記錄很是整潔,不管是線上回滾仍是 CodeReview 都更輕鬆;但倒是一個有隱患的操做,使用時務必謹慎。 git merge 操做更安全,同時也更簡單;但卻會增長一些冗餘的 commit 記錄。

這兒簡單說說 rebase 的合併流程和注意事項吧。看下圖

img

有三個點須要注意: ✦ rebase 先找出共同的祖先節點 ✦ 從祖先節點把 pay 分支的提交記錄摘下來,而後 rebase 到 master 分支 ✦ rebase 以後的 commitID 其實已經發生了變化 尤爲是第三點,常常會讓人誤操做,因此務必注意。

試想一下,開發過程當中,若是咱們頻繁的 rebase master 分支,會有什麼後果呢?

img

當你不斷 rebase master 的時候,其實你本地的 d 都變成了 d` ,再要和遠端 pay 分支保持一致,你的本地分支 commit 記錄已經不堪入目了。

另外要注意,毫不要在公共的分支上使用 rebase!!!

img

因此,爲了安全,團隊能夠考慮採用 merge。

pull request,方便CodeReview

Git 不只提供了代碼託管以及代碼開發的幫助,還提供了代碼審覈相似的功能。 當咱們在功能分支開發完成以後,能夠發起一個 pull request 請求,選擇須要對比的兩個分支

img

它會建立一個 pull request,制定相關人員來對代碼進行 review。 一般狀況下,團隊應該鼓勵交叉 review,涉及到公共代碼的時候,必定要讓相關人 review。

git hook,Git 的生命週期

這個大多數人應該都,據說過,git操做有它自身的生命週期,在不一樣的生命週期,咱們能夠作一些自動化的事情。

舉兩個簡單的例子: ✦ pre-commit的時候咱們能夠作 eslint ✦ post-commit的時候,咱們能夠作利用 jenkins 相似的工具作持續集成

固然還有更多的聲明週期,具體能夠參考 Git 鉤子

git submodule && git subtree,管理第三方模塊

這兩個命令一般用來管理公用的第三方模塊。好比一些通用的底層邏輯、中間件、還有一些可能會頻繁變化的通用業務組件。 固然,二者仍是有區別的。 git submodule 主要用來管理一些單向更新的公共模塊或底層邏輯。 git subtree 對於部分須要雙向更新的可複用邏輯來講,特別適合管理。好比一些須要複用的業務組件代碼。在我以前的實踐中,我也曾用subtree來管理構建系統邏輯。

git alias,簡化 Git 命令

咱們能夠經過配置 git alias 來簡化須要輸入的 Git 命令。 好比前文的 git subtree 須要輸入很長的 Git 命令,咱們能夠配置 .git/config 文件來解決。

// git stpull appfe demo/xxx
// git stpush appfe demo/xxx
[alias]
    stpull = !git subtree pull --prefix=$1 appfe $2 \
        && :
    stpush = !git subtree pull --prefix=$1 appfe $2 \
        && git subtree split --rejoin --prefix=$1 $2 \
        && git subtree push --prefix=$1 appfe $2 \
        && :
複製代碼

總結說點啥?

該文首先介紹了 Git 常規操做 ✦ 包括克隆代碼、操做 commit、操做分支等。其實 Git 常規操做的命令並很少,請看第一部分的簡單總結。

其次介紹了 Git 開發流程 ✦ 該部分主要介紹了兩種主流的開發模式:比較輕量的 基於功能分支的開發流程 和適合複雜項目的 GitFlow 開發流程 ,兩種模式各有使用的場景,對於常規使用,前者就已經足夠了。

最後介紹了一些 Git 實用技巧 ✦ 主要包括:reflog 操做,壓縮日誌,rebase 的注意事項,利用 pull request 作 codeReview,利用 git hook 作一些自動化工做等。

相關閱讀

Spark 灰度發佈在十萬級節點上的成功實踐

EMR常見FAQ

Ceph部署mon出現0.0.0.0地址問題定位

【每日課程推薦】機器學習實戰!快速入門在線廣告業務及CTR相應知識

此文已由做者受權騰訊雲+社區發佈,更多原文請點擊

搜索關注公衆號「雲加社區」,第一時間獲取技術乾貨,關注後回覆1024 送你一份技術課程大禮包!

海量技術實踐經驗,盡在雲加社區

相關文章
相關標籤/搜索