git merge和rebase的區別與選擇

git merge和rebase的區別與選擇

轉自:https://github.com/geeeeeeeeek/git-recipes/wiki/5.1-%E4%BB%A3%E7%A0%81%E5%90%88%E5%B9%B6%EF%BC%9AMerge%E3%80%81Rebase-%E7%9A%84%E9%80%89%E6%8B%A9#merge

BY 童仲毅(geeeeeeeeek@github)

這是一篇在原文(BY atlassian)基礎上演繹的譯文。除非另行注明,頁面上所有內容采用知識共享-署名(CC BY 2.5 AU)協議共享。

git rebase 這個命令經常被人認為是一種 Git 巫術,初學者應該避而遠之。但如果使用得當的話,它能給你的團隊開發省去太多煩惱。在這篇文章中,我們會比較 git rebase 和類似的 git merge 命令,找到 Git 工作流中 rebase 的所有用法。

概述

你要知道的第一件事是,git rebasegit merge 做的事其實是一樣的。它們都被設計來將一個分支的更改并入另一個分支,只不過方式有些不同。

想象一下,你剛創建了一個專門的分支開發新功能,然后團隊中另一個成員在 master 分支上添加了新的提交。這就會造成提交歷史被 fork 一份,用 Git 來協作的開發者應該都很清楚

在這里插入圖片描述

現在,如果 master 中新的提交和你的工作是相關的。為了將新的提交并入你的分支,你有兩個選擇:merge 或 rebase。

merge

將 master 分支合并到 feature 分支最簡單的辦法就是用下面這些命令:

git checkout feature
git merge master

或者,你也可以把它們壓縮在一行里。

git merge master feature

feature 分支中新的合并提交(merge commit)將兩個分支的歷史連在了一起。你會得到下面這樣的分支結構:

在這里插入圖片描述

Merge 好在它是一個安全的操作。現有的分支不會被更改,避免了 rebase 潛在的缺點(后面會說)。

另一方面,這同樣意味著每次合并上游更改時 feature 分支都會引入一個外來的合并提交。如果 master 非常活躍的話,這或多或少會污染你的分支歷史。雖然高級的 git log 選項可以減輕這個問題,但對于開發者來說,還是會增加理解項目歷史的難度。

rebase

作為 merge 的替代選擇,你可以像下面這樣將 feature 分支并入 master 分支:

git checkout feature
git rebase master

它會把整個 feature 分支移動到 master 分支的后面,有效地把所有 master 分支上新的提交并入過來。但是,rebase 為原分支上每一個提交創建一個新的提交,重寫了項目歷史,并且不會帶來合并提交。

在這里插入圖片描述

rebase最大的好處是你的項目歷史會非常整潔。首先,它不像 git merge 那樣引入不必要的合并提交。其次,如上圖所示,rebase 導致最后的項目歷史呈現出完美的線性——你可以從項目終點到起點瀏覽而不需要任何的 fork。這讓你更容易使用 git loggit bisectgitk 來查看項目歷史。

不過,這種簡單的提交歷史會帶來兩個后果:安全性和可跟蹤性。如果你違反了 rebase 黃金法則,重寫項目歷史可能會給你的協作工作流帶來災難性的影響。此外,rebase 不會有合并提交中附帶的信息——你看不到 feature 分支中并入了上游的哪些更改。

交互式rebase

交互式的 rebase 允許你更改并入新分支的提交。這比自動的 rebase 更加強大,因為它提供了對分支上提交歷史完整的控制。一般來說,這被用于將 feature 分支并入 master 分支之前,清理混亂的歷史。

-i 傳入 git rebase 選項來開始一個交互式的rebase過程:

git checkout feature
git rebase -i master

它會打開一個文本編輯器,顯示所有將被移動的提交:

pick 33d5b7a Message for commit #1
pick 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3

這個列表定義了 rebase 將被執行后分支會是什么樣的。更改 pick 命令或者重新排序,這個分支的歷史就能如你所愿了。比如說,如果第二個提交修復了第一個提交中的小問題,你可以用 fixup 命令把它們合到一個提交中:

pick 33d5b7a Message for commit #1
fixup 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3

保存后關閉文件,Git 會根據你的指令來執行 rebase,項目歷史看上去會是這樣:

在這里插入圖片描述

忽略不重要的提交會讓你的 feature 分支的歷史更清晰易讀。這是 git merge 做不到的。

Rebase 的黃金法則

當你理解 rebase 是什么的時候,最重要的就是什么時候 不能 用 rebase。git rebase 的黃金法則便是,絕不要在公共的分支上使用它。

比如說,如果你把 master 分支 rebase 到你的 feature 分支上會發生什么:

在這里插入圖片描述

這次 rebase 將 master 分支上的所有提交都移到了 feature 分支后面。問題是它只發生在你的代碼倉庫中,其他所有的開發者還在原來的 master 上工作。因為 rebase 引起了新的提交,Git 會認為你的 master 分支和其他人的 master 已經分叉了。

同步兩個 master 分支的唯一辦法是把它們 merge 到一起,導致一個額外的合并提交和兩堆包含同樣更改的提交。不用說,這會讓人非常困惑。

所以,在你運行 git rebase 之前,一定要問問你自己「有沒有別人正在這個分支上工作?」。如果答案是肯定的,那么把你的爪子放回去,重新找到一個無害的方式(如 git revert)來提交你的更改。不然的話,你可以隨心所欲地重寫歷史。

強制推送

如果你想把 rebase 之后的 master 分支推送到遠程倉庫,Git 會阻止你這么做,因為兩個分支包含沖突。但你可以傳入 --force 標記來強行推送。就像下面一樣:

# 小心使用這個命令!
git push --force

它會重寫遠程的 master 分支來匹配你倉庫中 rebase 之后的 master 分支,對于團隊中其他成員來說這看上去很詭異。所以,務必小心這個命令,只有當你知道你在做什么的時候再使用。

僅有的幾個強制推送的使用場景之一是,當你在想向遠程倉庫推送了一個私有分支之后,執行了一個本地的清理(比如說為了回滾)。這就像是在說「哦,其實我并不想推送之前那個 feature 分支的。用我現在的版本替換掉吧。」同樣,你要注意沒有別人正在這個 feature 分支上工作。

工作流

rebase 可以或多或少應用在你們團隊的 Git 工作流中。在這一節中,我們來看看在 feature 分支開發的各個階段中,rebase 有哪些好處。

第一步是在任何和 git rebase 有關的工作流中為每一個 feature 專門創建一個分支。它會給你帶來安全使用 rebase 的分支結構:

在這里插入圖片描述

本地清理

在你工作流中使用 rebase 最好的用法之一就是清理本地正在開發的分支。隔一段時間執行一次交互式 rebase,你可以保證你 feature 分支中的每一個提交都是專注和有意義的。你在寫代碼時不用擔心造成孤立的提交——因為你后面一定能修復。

調用 git rebase 的時候,你有兩個基(base)可以選擇:上游分支(比如 master)或者你 feature 分支中早先的一個提交。我們在「交互式 rebase」一節看到了第一種的例子。后一種在當你只需要修改最新幾次提交時也很有用。比如說,下面的命令對最新的 3 次提交進行了交互式 rebase:

git checkout feature
git rebase -i HEAD~3

通過指定 HEAD~3 作為新的基提交,你實際上沒有移動分支——你只是將之后的 3 次提交重寫了。注意它不會把上游分支的更改并入到 feature 分支中。

在這里插入圖片描述

如果你想用這個方法重寫整個 feature 分支,git merge-base 命令非常方便地找出 feature 分支開始分叉的基。下面這段命令返回基提交的 ID,你可以接下來將它傳給 git rebase

git merge-base feature master

交互式 rebase 是在你工作流中引入 git rebase 的的好辦法,因為它只影響本地分支。其他開發者只能看到你已經完成的結果,那就是一個非常整潔、易于追蹤的分支歷史。

但同樣的,這只能用在私有分支上。如果你在同一個 feature 分支和其他開發者合作的話,這個分支是公開的,你不能重寫這個歷史。

用帶有交互式的 rebase 清理本地提交,這是無法用 git merge 命令代替的。

將上游分支更改并入feature分支

在概覽一節,我們看到了 feature 分支如何通過 git mergegit rebase 來并入上游分支。merge 是保留你完整歷史的安全選擇,rebase 將你的 feature 分支移動到 master 分支后面,創建一個線性的歷史。

git rebase 的用法和本地清理非常類似(而且可以同時使用),但之間并入了 master 上的上游更改。

記住,rebase 到遠程分支而不是 master 也是完全合法的。當你和另一個開發者在同一個 feature 分之上協作的時候,你會用到這個用法,將他們的更改并入你的項目。

比如說,如果你和另一個開發者 John 往 feature 分支上添加了幾個提交,在從 John 的倉庫中 fetch 之后,你的倉庫可能會像下面這樣:

在這里插入圖片描述

就和并入 master 上的上游更改一樣,你可以這樣解決這個 fork:要么 merge 你的本地分支和 John 的分支,要么把你的本地分支 rebase 到 John 的分支后面。

在這里插入圖片描述

注意,這里的 rebase 沒有違反 rebase 黃金法則,因為只有你的本地分支上的 commit 被移動了,之前的所有東西都沒有變。這就像是在說「把我的改動加到 John 的后面去」。在大多數情況下,這比通過合并提交來同步遠程分支更符合直覺。

默認情況下,git pull 命令會執行一次merge,但你可以傳入--rebase 來強制它通過rebase來整合遠程分支。

用 Pull Request 進行審查

如果你將 Pull Request 作為你代碼審查過程中的一環,你需要避免在創建 Pull Request 之后使用 git rebase。只要你發起了 Pull Request,其他開發者能看到你的代碼,也就是說這個分支變成了公共分支。重寫歷史會造成 Git 和你的同事難以找到這個分支接下來的任何提交。

來自其他開發者的任何更改都應該用 git merge 而不是 git rebase 來并入。

因此,在提交 Pull Request前用交互式的 rebase 進行代碼清理通常是一個好的做法。

并入通過的功能分支

如果某個功能被你們團隊通過了,你可以選擇將這個分支 rebase 到 master 分支之后,或是使用 git merge 來將這個功能并入主代碼庫中。

這和將上游改動并入 feature 分支很相似,但是你不可以在 master 分支重寫提交,你最后需要用 git merge 來并入這個 feature。但是,在 merge 之前執行一次 rebase,你可以確保 merge 是一直向前的,最后生成的是一個完全線性的提交歷史。這樣你還可以加入 Pull Request 之后的提交。

在這里插入圖片描述

如果你還沒有完全熟悉 git rebase,你還可以在一個臨時分支中執行 rebase。這樣的話,如果你意外地弄亂了你 feature 分支的歷史,你還可以查看原來的分支然后重試。

比如說:

git checkout feature
git checkout -b temporary-branch
git rebase -i master
# [清理目錄]
git checkout master
git merge temporary-branch

總結

你使用 rebase 之前需要知道的知識點都在這了。如果你想要一個干凈的、線性的提交歷史,沒有不必要的合并提交,你應該使用 git rebase 而不是 git merge 來并入其他分支上的更改。

另一方面,如果你想要保存項目完整的歷史,并且避免重寫公共分支上的 commit, 你可以使用 git merge。兩種選項都很好用,但至少你現在多了 git rebase 這個選擇。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/532543.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/532543.shtml
英文地址,請注明出處:http://en.pswp.cn/news/532543.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

java安全(六)java反序列化2,ysoserial調試

給個關注?寶兒! 給個關注?寶兒! 給個關注?寶兒! ysoserial 下載地址:https://github.com/angelwhu/ysoserial ysoserial可以讓?戶根據??選擇的利?鏈,?成反序列化利?數據&…

C++面試常見問題一

C面試常見問題一 轉自:https://oldpan.me/archives/c-interview-answer-1 原作者:[oldpan][https://oldpan.me/] 前言 這里收集市面上所有的關于算法和開發崗最容易遇到的關于C方面的問題,問題信息來自互聯網以及牛客網的C面試題目匯總。答題…

java安全(七) 反序列化3 CC利用鏈 TransformedMap版

給個關注?寶兒! 給個關注?寶兒! 給個關注?寶兒! 目錄圖解代碼demo涉及的接口與類:TransformedMapTransformerConstantTransformerInvokerTransformerChainedTransformerdome理解總結&#xff1a…

C++編譯時多態和運行時多態

C編譯時多態和運行時多態 作者:melonstreet 出處:https://www.cnblogs.com/QG-whz/p/5132745.html 本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接&#xff0…

java安全(八)TransformedMap構造POC

給個關注?寶兒! 給個關注?寶兒! 給個關注?寶兒! 上一篇構造了一個了commons-collections的demo 【傳送門】 package test.org.vulhub.Ser;import org.apache.commons.collections.Transformer; import org…

Pytorch Tutorial 使用torch.autograd進行自動微分

Pytorch Tutorial 使用torch.autograd進行自動微分 本文翻譯自 PyTorch 官網教程。 原文:https://pytorch.org/tutorials/beginner/basics/autogradqs_tutorial.html#optional-reading-tensor-gradients-and-jacobian-products 在訓練神經網絡時,最常使用…

TVM:編譯深度學習模型快速上手教程

TVM:編譯深度學習模型快速上手教程 本文將展示如何使用 Relay python 前端構建一個神經網絡,并使用 TVM 為 Nvidia GPU 生成一個運行時庫。 注意我們需要再構建 TVM 時啟用了 cuda 和 llvm。 TVM支持的硬件后端總覽 在本教程中,我們使用 cu…

TVM:設計與架構

TVM:設計與架構 本文檔適用于想要了解 TVM 架構和/或積極開發項目的開發人員。頁面組織如下: 示例編譯流程概述了 TVM 將模型的高層描述轉換為可部署模塊所采取的步驟。要開始使用,請先閱讀本節。 邏輯架構組件部分描述了邏輯組件。后面的部…

遞歸+回溯

遞歸-回溯 本文參考自代碼隨想錄視頻: https://www.bilibili.com/video/BV1cy4y167mM https://www.bilibili.com/video/BV1ti4y1L7cv 遞歸回溯理論基礎 只要有遞歸,就會有回溯,遞歸函數的下面的部分通常就是回溯的邏輯。 回溯是純暴力的搜索…

Nvidia CUDA初級教程1 CPU體系架構綜述

Nvidia CUDA初級教程1 CPU體系架構綜述 視頻:https://www.bilibili.com/video/BV1kx411m7Fk?p2 講師:周斌 本節內容:了解現代CPU的架構和性能優化: 流水線 Pipelining分支預測 Branch Prediction超標量 Superscalar亂序執行 Out…

Nvidia CUDA初級教程2 并行程序設計概述

Nvidia CUDA初級教程2 并行程序設計概述 視頻:https://www.bilibili.com/video/BV1kx411m7Fk?p3 講師:周斌 本節內容: 為什么需要?怎么做?一些技術和概念 串并行計算模式 串行計算模式 常規軟件時串行的 設計運行…

Nvidia CUDA初級教程4 GPU體系架構概述

Nvidia CUDA初級教程4 GPU體系架構概述 視頻:https://www.bilibili.com/video/BV1kx411m7Fk?p5 講師:周斌 本節內容: 為什么需要GPU三種方法提升GPU的處理速度實際GPU的設計舉例: NVDIA GTX 480: FermiNVDIA GTX 680: Kepler GP…

Nvidia CUDA初級教程5 CUDA/GPU編程模型

Nvidia CUDA初級教程5 CUDA/GPU編程模型 視頻:https://www.bilibili.com/video/BV1kx411m7Fk?p6 講師:周斌 本節內容: CPU和GPU互動模式GPU線程組織模型(需要不停強化)GPU存儲模型基本的編程問題 CPU與GPU交互 各自…

Nvidia CUDA初級教程6 CUDA編程一

Nvidia CUDA初級教程6 CUDA編程一 視頻:https://www.bilibili.com/video/BV1kx411m7Fk?p7 講師:周斌 GPU架構概覽 GPU特別使用于: 密集計算,高度可并行計算圖形學 晶體管主要被用于: 執行計算而不是 緩存數據控制指令…

由前中后遍歷序列構建二叉樹

由前/中/后遍歷序列構建二叉樹 基礎 首先,我們需要知道前中后序三種深度優先遍歷二叉樹的方式的具體順序: 前序:中左右中序:左中右后序:左右中 另外,要知道只有中序前/后序可以唯一確定一棵二叉樹&…

手寫nms

手寫nms 計算寬高的時候加1是為什么? 本文總結自互聯網的多種nms實現,供參考,非博主原創,各原文鏈接如下,也建議大家動手寫一寫。 Ref: 淺談NMS的多種實現 目標窗口檢測算法-NMS非極大值抑制 一、fas…

目標檢測綜述

目標檢測綜述 轉自:https://zhuanlan.zhihu.com/p/383616728 論文參考:[Object Detection in 20 Years: A Survey][https://arxiv.org/abs/1905.05055] 引言 目標檢測領域發展至今已有二十余載,從早期的傳統方法到如今的深度學習方法&#x…

Nvidia CUDA初級教程7 CUDA編程二

Nvidia CUDA初級教程7 CUDA編程二 視頻:https://www.bilibili.com/video/BV1kx411m7Fk?p8 講師:周斌 本節內容: 內置類型和函數 Built-ins and functions線程同步 Synchronizing線程調度 Scheduling threads存儲模型 Memory model重訪 Matr…

詳解優酷視頻質量評價體系

萬字長文 | 詳解優酷視頻質量評價體系 分享嘉賓|李靜博士,阿里巴巴文娛集團資深算法專家,阿里巴巴大文娛摩酷實驗室視頻體驗與質量團隊負責人 整理出品|AICUG人工智能社區 本文地址:https://www.6aiq.com/article/1617…

視頻質量評價:挑戰與機遇

視頻質量評價:挑戰與機遇 轉自:https://zhuanlan.zhihu.com/p/384603663 本文整理自鵬城實驗室助理研究員王海強在LiveVideoStack線上分享上的演講。他通過自身的實踐經驗,詳細講解了視頻質量評價的挑戰與機遇。 文 / 王海強 整理 / LiveVi…