歡迎你們前往騰訊雲+社區,獲取更多騰訊海量技術實踐乾貨哦~javascript
Git 是一個分佈式的代碼管理容器,本地和遠端都保有一份相同的代碼。 Git 倉庫主要是由是三部分組成:本地代碼,緩存區,提交歷史,這幾乎是全部操做的本質,可是爲了文章更加簡單易懂,就不圍繞這塊展開了,有興趣的能夠去了解下。 開門見山,咱們直接來講說 Git 有哪些常見的操做。git
咱們簡單說說Git有哪些常規操做,可以讓咱們應付簡單的開發需求。github
✦ 克隆遠端代碼緩存
git clone + 遠程庫地址
複製代碼
✦ 查看本地的代碼狀態安全
// 能夠明確的呈現出本地倉庫的狀態
// 哪些文件發生改動,哪些文件已經提交到本機
// 以及一些操做指示。
git status
複製代碼
✦ 同步遠端分支變化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 都是一份完整的代碼狀態,用一個 commitID 來惟一標誌。
從某個角度上來講,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其實已經發生變化。
相對來講,git merge 處理衝突更直接,而git rebase 可以保證清晰的 commit 記錄。
合併 commit 的時候,一般會發生衝突。 能夠全局搜索特殊字符好比<<<
,找到須要處理的代碼位置,而後認真分析應該保留哪一部分代碼。
在團隊協做的時候,分支是必不可少的。那麼應該如何對分支進行操做呢?
所謂的分支其實就是一個指向 commitID 的指針,你能夠去.git/refs/heads
裏去看看。
一般狀況下,咱們建議分支至少可以明確的標記功能名稱,若是能標記用戶就更好了,好比qixiu/feature
。
✦ 查看分支
能夠同時看到本地分支和遠端分支,配合上前文介紹的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 有一些成熟的開發流程,比較主流的有兩種:基於功能分支的開發流程 和 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 開發流程中幾個約定的分支,以及他們各自承擔的角色是怎麼樣的?
✦ Master分支:用於存放線上版本代碼,能夠方便的給代碼打版本號。 ✦ Develop分支:用於整合 Feature 分支。 ✦ Feature分支:某個功能的分支,從 Develop 分支切出,而且功能完成時又合併回 Develop 分支,不直接和 Master 分支交互。 ✦ Release分支:一般對應一個迭代。將一個版本的功能所有合併到 Develop 分支以後,從 Develop 切出一個 Release 分支。這個分支不在追加新需求,能夠完成 bug 修復、完善文檔等工做。務必記住,代碼發佈後,須要將其合併到 Master 分支,同時也要合併到 Develop 分支。 ✦ Hotfix分支:緊急修復的分支,是惟一能夠從 Master 切出的分支,一旦修復了能夠合併到 Master 分支和 Develop 分支。
從每一個分支的功能和約定能夠看出,它流程多約束多,對於小規模應用並不適合。 固然 GitFlow 有一些輔助工具 gitflow 能夠自動化的完成這些任務,對於大型項目也頗有幫助。
前面講了 Git 有哪些基本操做,而後介紹了兩個主流的工做流程。 接下來咱們看看 Git 有哪些特別的技巧值得一提。
Git 操做除了基本的代碼管理功能,還有一些小技巧可以讓你眼前一亮。
這個我必定要放在第一個介紹,由於它曾經數次解救了個人代碼
仔細看上圖,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 commit
✦ git push -f origin branchName
,由於會有衝突,因此須要強制覆蓋遠端分支,請務必謹慎。 ✦ 合併到 master 中,而後更新遠端 master。
此外還有兩種壓縮日誌的辦法: git commit --amend
:追加 commit 到上一個 commit 上。 git rebase -i
:經過交互式的 rebase,提供對分支 commit 的控制,從而能夠清理混亂的歷史。
從實際應用來講,三種日誌壓縮都很優秀,git reset
更簡單,git rebase -i
更細膩。
前文簡單介紹了 git rebase
和 git merge
的區別,坦率講,他們各有優劣。 git rebase
能讓你的 commit 記錄很是整潔,不管是線上回滾仍是 CodeReview 都更輕鬆;但倒是一個有隱患的操做,使用時務必謹慎。 git merge
操做更安全,同時也更簡單;但卻會增長一些冗餘的 commit 記錄。
這兒簡單說說 rebase 的合併流程和注意事項吧。看下圖
有三個點須要注意: ✦ rebase 先找出共同的祖先節點 ✦ 從祖先節點把 pay 分支的提交記錄摘下來,而後 rebase 到 master 分支 ✦ rebase 以後的 commitID 其實已經發生了變化 尤爲是第三點,常常會讓人誤操做,因此務必注意。
試想一下,開發過程當中,若是咱們頻繁的 rebase master 分支,會有什麼後果呢?
當你不斷 rebase master 的時候,其實你本地的 d 都變成了 d` ,再要和遠端 pay 分支保持一致,你的本地分支 commit 記錄已經不堪入目了。
另外要注意,毫不要在公共的分支上使用 rebase!!!
因此,爲了安全,團隊能夠考慮採用 merge。
Git 不只提供了代碼託管以及代碼開發的幫助,還提供了代碼審覈相似的功能。 當咱們在功能分支開發完成以後,能夠發起一個 pull request 請求,選擇須要對比的兩個分支
它會建立一個 pull request,制定相關人員來對代碼進行 review。 一般狀況下,團隊應該鼓勵交叉 review,涉及到公共代碼的時候,必定要讓相關人 review。
這個大多數人應該都,據說過,git操做有它自身的生命週期,在不一樣的生命週期,咱們能夠作一些自動化的事情。
舉兩個簡單的例子: ✦ pre-commit的時候咱們能夠作 eslint ✦ post-commit的時候,咱們能夠作利用 jenkins 相似的工具作持續集成
固然還有更多的聲明週期,具體能夠參考 Git 鉤子
這兩個命令一般用來管理公用的第三方模塊。好比一些通用的底層邏輯、中間件、還有一些可能會頻繁變化的通用業務組件。 固然,二者仍是有區別的。 git submodule
主要用來管理一些單向更新的公共模塊或底層邏輯。 git subtree
對於部分須要雙向更新的可複用邏輯來講,特別適合管理。好比一些須要複用的業務組件代碼。在我以前的實踐中,我也曾用subtree來管理構建系統邏輯。
咱們能夠經過配置 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 作一些自動化工做等。
相關閱讀
此文已由做者受權騰訊雲+社區發佈,更多原文請點擊
搜索關注公衆號「雲加社區」,第一時間獲取技術乾貨,關注後回覆1024 送你一份技術課程大禮包!
海量技術實踐經驗,盡在雲加社區!