主頁 > .NET開發 > 功能分支在合并到Master后發生了變化

功能分支在合并到Master后發生了變化

2021-11-19 03:39:36 .NET開發

我有一個feature分支,我需要合并到其中,master所以我通過 github 創建了一個拉取請求并將其合并。

我原以為featurebrach中的所有更改master將覆寫該特定檔案,master但在合并后我注意到相反的特性分支更新了代碼(主檔案中不同的代碼)并且主檔案保持不變。

如果我錯了,請糾正我的理解。當我們將分支 A 合并到分支 B 時,分支 A 不應更改。不是嗎?

謝謝,

uj5u.com熱心網友回復:

我猜你跑了git merge master這將 master 合并到當前分支中。

要將 feature 分支合并到 master 中,需要切換到 master 分支,然后運行git merge feature. 話雖如此,您可以在不將功能合并到母版中的情況下創建 PR。

uj5u.com熱心網友回復:

我期望feature分支中與 不同的所有更改master將覆寫該特定檔案master...

這種期望是錯誤的。

合并并不意味著使相同合并意味著合并作業

這有點復雜:Git 不存盤您所做的作業。Git的商店,而是充滿快照每個檔案那是:

  • 每個提交都有編號,有一個大的、丑陋的、唯一的哈希 ID這個數字是 Git 從 Git 的主資料庫中實際檢索提交的方式。(這個資料庫包含提交和其他支持物件,所有這些都有這些丑陋的大哈希 ID。)

  • 每個提交存盤兩件事:

    • 提交具有每個檔案的完整快照。每個提交中的檔案都以特殊的、只讀的、僅限 Git 的、壓縮和重復資料洗掉的格式存盤。如果您有一個包含大量提交的存盤庫,并且您檢查了一個包含一些非常大的檔案和一些非常小的檔案的提交,并且您只更改其中一個小檔案并添加并提交,則 Git 必須存盤所有檔案重來一遍,但它可以重用除了一個更改過的檔案之外的所有檔案。因此,只有更改后的檔案才實際占用任何空間。但是每次提交仍然有每個檔案!

    • 提交還存盤一些元資料,或有關提交本身的資訊。這包括您在git log輸出中看到的內容:例如,誰進行了提交、何時提交以及為什么(他們的日志訊息)。出于 Git 自身的目的,每個提交也在此元資料中存盤先前提交哈希 ID串列

這個先前提交哈希 ID 串列通常只有一個條目。我們稱該條目為提交的條目這意味著每個孩子提交“指向”其父母:

... <-F <-G <-H

這里H代表最新提交的哈希 ID 這個提交是一個提交,所以它有一個快照——所有檔案和你制作時的格式一樣H——和元資料。元資料說你是去年八月做的,或者別的什么。它還說提交H是較早的提交G(無論真實的、隨機的哈希 ID 是什么:git log都會顯示它)。

G但是,Commit是一次提交,因此它具有每個檔案的完整快照和一些元資料。Git 可以提取兩個提交(到記憶體中的臨時區域)并比較檔案當檔案完全匹配時——因此被洗掉重復——這很無聊,而且 Git 通常什么都不說。當檔案匹配時,Git 可以想出一個配方——一組應用于舊檔案的更改——使其與新檔案匹配。這就是你在git log -p.

已將提交顯示H較早提交更改Ggit log現在后退一跳。現在它的作業是顯示 commit G為此,它需要提交FG的母公司獲得快照弄清楚發生了什么變化,如果你想看到的是,但那是容易的,因為G持有F的哈希ID。

因此,Git 可以向您顯示作者和訊息等資訊G,然后與Fto的差異G以查看更改的內容,現在 Git 可以再次向后移動一跳并顯示給您F這是一個提交,所以它有一個快照和一個父項,而且......好吧,這個想法現在應該很明顯了。

That's all well and good for simple cases, but we have one problem: we have to somehow give the hash ID for commit H to Git. We could scribble it onto a whiteboard, or jot it down on paper. But why should we do that, when we have a computer? Let's have Git store this hash ID for us, in—say—a branch name. And that's just what we do.

Now, if we have a simple chain of commits like this:

...--F--G--H   <-- master (HEAD)

and we create a new branch name feature, we get:

...--F--G--H   <-- feature, master (HEAD)

We're currently using commit H, via the name master. If we switch to feature, with git checkout feature or git switch feature, we switch to using commit H via the name feature:

...--F--G--H   <-- feature (HEAD), master

Nothing else has to change, so Git takes a shortcut and changes nothing else: we're still using commit H, just through another name.

If we now make new commits, these new commits get:

  • a new snapshot, from what we tell Git to use;
  • new metadata: your name as author/committer and "now" as the date and time, with the parent commit being the current commit.

By writing out the new commit, Git acquires a new hash ID—there's some fairly deep magic here, using cryptographic hashes, which also explains why nothing about any commit can ever change once you've made it—but we'll just call our new commit I. New commit I will point back to existing commit H:

             I
            /
...--F--G--H

and now Git pulls its clever little trick: it writes I's hash ID into the current branch name, i.e., feature:

             I   <-- feature (HEAD)
            /
...--F--G--H   <-- master

If we make yet another new commit before we do anything else, we get:

             I--J   <-- feature (HEAD)
            /
...--F--G--H   <-- master

If we now switch back to the name master, here's what happens:

             I--J   <-- feature
            /
...--F--G--H   <-- master (HEAD)

We've now had Git attach the special name HEAD to the name master, which points to commit H, not commit J. Since we're changing commits, Git will now remove, from our working tree, all the files from J and put in all the files from H instead (using the snapshots).1

If we were to run git merge feature now, you'd get the thing you expected. But before we do, let's make more commits. We'll modify some file that also got modified in I and/or J, as we make two new commits K and L:

             I--J   <-- feature
            /
...--F--G--H
            \
             K--L   <-- master (HEAD)

If we compare the files in J vs the files in L (in either order), we'll get a recipe that would change what's in one of those two commits to match what's in the other. But if we run git merge feature, we don't want to lose the good stuff we did in commits K-L. So that's not what git merge does.

Instead, git merge:

  • locates the current commit: that's easy, it's whatever HEAD is attached to, and we already have that commit checked out too, as --ours;
  • locates the other commit, in this case commit J, from the name we supply: we can actually give a raw hash ID as Git just needs the commit; this becomes the --theirs commit;
  • and, last, uses the graph we've been drawing to find the best shared starting-point commit.

That last commit is obvious from the drawing here: it's commit H. Commit H is on both branches. Commits I-J are only on feature, and commits K-L are only on master, but all commits up to and including H are on both branches. So all those commits are shared, and H is obviously the best one.2

Now, to do the merge, Git will:

  • compare the snapshot in H to that in L: that shows what you did, on branch master, to get to the --ours commit;
  • compare the snapshot in H to that in J: that shows that they did, on branch feature, to get to the --theirs commit;
  • combine the two sets of changes.

The combined changes then get applied to the snapshot from H. That keeps our changes and adds theirs, or, equivalently, keeps their changes and adds ours. Either way, what ends up in the files doesn't necessarily match either commit J or commit L, because we took two sets of changes.

If all goes well, Git makes a new merge commit. A merge commit is exactly the same as any other commit: it has a snapshot, and a list of parent hash IDs. What makes it a merge commit is that the list of parent hash IDs has not just one hash ID, but two:3

             I--J   <-- feature
            /    \?
...--F--G--H      M
            \    /1
             K--L   <-- master (HEAD)

There's still just the one snapshot. The first parent, marked with a tiny 1 here, leads back to the commit we were on when we started the git merge. The second parent leads back to the commit we told Git to merge.

Note that in the much simpler case of:

             I--J   <-- feature
            /
...--F--G--H   <-- master (HEAD)

Git still does all the fancy merge-base calculation. This time, however, our commit is H, theirs is J, and the merge base is ... H again. If Git were to compare the snapshot in H vs the snapshot in H, the list of changes it would find would be empty.

We can force Git to do that anyway, with git merge --no-ff. The result is a new merge commit, with two parents as usual:

             I--J   <-- feature
            /    \
...--F--G--H------M   <-- master (HEAD)

but now the snapshot in M really does match the snapshot in J. That's because Git compared H to J to see what they changed, then applied those changes to H, and used no changes from our side, to make the snapshot. Algebraically,4 H (J - H) is just J again.

If we don't force a real merge, Git will do a sort of fake not-actually-a-merge, called a fast forward. But GitHub won't let you do a fast-forward, if you use their clicky buttons: they have MERGE, REBASE AND MERGE, and SQUASH AND MERGE and none of those is Git's internal fast-forward. (The REBASE AND MERGE option comes close, but isn't the same.)


1This explanation deliberately skips a lot of weird corner cases that Git allows.

2Proof by vigorous hand waving, number 8 on the list. More seriously, see Lowest Common Ancestor of a DAG.

3Technically, a Git merge can have more than two parents, but that's rare (and mainly used for showing off ??).

4Some version control systems do attempt to define an algebra of changes, and hence do this sort of computation. It ... gets messy.

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/360180.html

標籤:混帐 github 合并 特征分支

上一篇:當我的github有另一個提交并且我忘記在github中拉我的提交時如何推送我的本地提交

下一篇:如何在vimdiff中撤消dp(或:diffput),“u”不起作用

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more