主頁 > 移動端開發 > 為什么master分支在`commit`更改之前也會更改

為什么master分支在`commit`更改之前也會更改

2021-12-10 06:22:49 移動端開發

  • 有時我在第二個分支中寫了一些更改,但我還不想提交,
  • 在那里我回到 master 我發現 master 分支也改變了,為什么?
$ mkdir tmp && cd $_ && git init && touch file.txt && echo "text wite on master" > file.txt
$ git add file.txt && git commit -m"init"
  • 結帳第二個分支
$ git checkout -b seconde-branch && echo "text wite on seconde branch" >> file.txt
  • 在不提交更改的情況下切換回 master
$ git checkout -b master 
$ cat file.txt

text wite on master
text wite on seconde branch
  • 它應該是輸出:text wite on master
  • 同樣,當我在 master 中使用 git restore 時,我丟失了在第二個分支中寫入的更改,這使我避免使用分支,因為它令人困惑

uj5u.com熱心網友回復:

您在作業樹中看到和處理的檔案不在任何分支中

理解這一點的方法是記住以下規則:

  1. Git 是關于commits 的
  2. Git 與files無關,盡管提交持有檔案。
  3. Git 與分支無關,盡管分支名稱可以幫助我們(和 Git)找到提交。

Git 關心的是——Git存盤什么傳輸到其他 Git 存盤庫——是提交

每次提交:

  • 被編號:每個提交都有一個大的、丑陋的、隨機的、唯一的哈希 ID某些提交的哈希 ID 是 Git 知道該提交就是該提交的方式。您的 Git 會將這個哈希 ID 呈現給其他一些 Git 軟體;如果使用其存盤庫的其他 Git 軟體使用此編號進行提交,則它具有提交。如果它沒有此編號,則它需要從您的 Git 存盤庫中獲取此提交(如果您的 Git 提供)。(在另一個方向也是如此,當您讓 Git 向您的存盤庫添加新提交時,這些提交是從其他 Git 存盤庫獲得的。)

  • 是只讀的:任何提交都不能更改,甚至 Git 本身也不能更改。

  • 存盤兩件事:當您或任何人提交時 Git 知道的每個檔案的完整快照;和一些元資料,或者關于提交的資訊,比如誰做的,什么時候做的。請注意,存盤在提交中的檔案以特殊的、只讀的、僅限 Git 的格式保存,并進行了壓縮和重復資料洗掉。您的計算機無法讀取這些檔案(好吧,它可以讀取原始資料,但無法理解它們)并且沒有任何東西——甚至 Git 本身——可以覆寫這些檔案(因為用于提交)。

由于提交及其檔案只能由 Git 本身讀取,因此 Git 必須先提取提交,然后才能對其進行任何操作。這就是git checkout它的作用:它提取提交。

當你從一個分支切換到另一個分支時——無論是 withgit checkout還是較新的git switch——你可能是在告訴 Git 從一個提交切換到另一個提交。在這種情況下,Git 必須洗掉您正在使用的提交中產生的檔案,并將它們替換為您使用的提交中產生的檔案不過,在 Git 執行此操作之前,它會檢查以確保它洗掉和替換的任何檔案實際上都沒有被修改。這樣你就不會失去你已經完成但尚未提交的作業。

如果你已經完成了作業,但還沒有提交,那么到目前為止你所做的作業不在 Git 中只是在 Git 之前提取的檔案中,您從那時起進行了更改。因此從一個分支切換到另一個分支不會顯示任何內容,因為這些檔案不在 Git 中

整個系統可能非常混亂,所以讓我們多說一點。

提交已編號,并鏈接到較早的提交

每當您或任何人進行提交時,新提交都會獲得一個新的、唯一的、隨機的哈希 ID。該散列 ID 與宇宙中任何地方的每個其他提交的散列 ID 不同,而且必須如此。1 新提交被寫出,從那時起,它就永遠無法更改。

新提交在寫出時可以將一些舊提交的哈希 ID 存盤在其中。這使得新提交“指向”舊提交。一旦我們重復了幾次這個技巧,我們就有了一個提交鏈。如果我們用單個大寫字母來稱呼它們——這對人類來說更容易理解——我們得到的圖是這樣的:

A <-B <-C

C最新的提交在哪里我們說,提交B,里面傳來之前C,是C提交C 指向其父級BCommitC還保存了每個檔案的完整快照。B當然,Commit也是一次提交,它保存每個檔案的完整快照并指向其父檔案A提交A是一個提交并保存一個快照,但由于提交A是第一次提交,它不能向后指向任何更早的提交,所以它只是沒有。

通過從最新的提交開始并向后作業,Git 可以找到所有提交。所以我們只需要記住最后一次提交的哈希 ID。


1這在技術上是不可能的,總有一天 Git 將無法作業。大尺寸的哈希 ID 試圖將這一天推遲到很遠的將來,以至于我們不在乎它實際上不會永遠有效:在出現問題之前,我們都會死很久。至少,這是一個想法,但我們已經遇到了一些其他的小問題,所以 Git 正在獲得一個新的更大的哈希 ID 方案。


分支名稱幫助我們(和 Git)找到提交

The system above works fine as long as we remember the actual hash ID of commit C. But who can remember some big ugly hexadecimal number like that? I can't, and you probably can't. We could write these down, perhaps ... but hey, wait a minute, we have a computer. Let's have the computer store the number of the latest commit. We'll put it in a small database of names. Let's call them branch names and tag names and the like.

Now that we have names, we can add them to our drawing. Each name points to some commit:

A--B--C   <-- master

Here, the branch name master points to commit C. Let's add another branch name, seconde-branch, that also points to commit C, like this:

A--B--C   <-- master, seconde-branch

We now need a way to remember which name we are using. Let's use the special name HEAD for this:

A--B--C   <-- master (HEAD), seconde-branch

This indicates that we are using commit C as our current commit, via the name master. If we now:

git checkout seconde-branch

we get:

A--B--C   <-- master, seconde-branch (HEAD)

We're still using commit C, but now we're using it via the name seconde-branch.

When we change branches like this, we're not changing which commit we're using. So Git does not have to remove-and-replace any files at all, and therefore, Git doesn't bother. This lets us switch to the other branch, in case we forgot and started editing files too soon.

Git's index and your working tree

As I mentioned above, when we first check out or switch to some branch, Git will—if needed—extract all the files from the snapshot in the commit as found by the branch name. These files are in some weird Git-only format, compressed and de-duplicated, but now they're regular everyday files.

These files go in a work area. Git calls this our working tree or work-tree. The files here came out of a commit but are not actually in Git: they're just ordinary files in ordinary folders. Git has no control over these files: you can do anything you want with them.

When you have done something with them, you'd typically like to save the things you did. For this purpose you'll need to make a new commit. In other version control systems, you'd run their commit verb (e.g., hg commit or svn commit) and they'd scan your working tree, find what you changed, and make the new commit. Git, however, is different. Git makes you run git add.

What git add does is copy the updated file back into a secret—well, not really secret, but invisible—Git area that, in effect, sits between a commit and your working tree. This area is extremely important in Git, at least if you ever plan to make any new commits. (If you don't need new commits, you can mostly ignore it.) Because it is so important, and/or because it is badly named, this area has three names: Git calls it the index, the staging area, and—rarely these days—the cache.

(You can—to a limited extent—get by with git commit -a instead of git add. Don't do this! You'll be able to ignore the index for a while, but eventually, Git will whack you over the head with its index. Learn about the index. Embrace it. Some people find it useful: there are clever tricks you can do with it. Some find it annoying, but it's there, in the way, and you need to know about it so you don't trip over it.)

Git's index is a complicated thing, but it plays one pretty constant role, and can therefore be described in one line this way: The index holds your proposed next commit. The initial git checkout or git switch that you run extracts the commit's files to Git's index.

The files in Git's index are in the compressed and de-duplicated form that Git uses internally. The key difference between these files, and the files in a commit, is that the commit cannot be changed, but the index contents can be changed. Running git add tells Git: Make the index copy of this file look like the work-tree copy.

What this means is that after git add, you've updated your proposed next commit. When you first check out commit C, or are on commit C with modified working tree files like this:

A--B--C   <-- master, seconde-branch (HEAD)

the index still holds the original files that were extracted from commit C. Until you run git commit—which will write out the index's files into a permanent form in a new commit—the index copies are just sitting around ready to go into a new commit.

Running git add updates the index copies, making them match the working tree copies. So this means that with, e.g., file.txt, there are three copies:

  HEAD         index      work-tree
---------    ---------    ---------
file.txt     file.txt     file.txt

As you modify the work-tree copy, nothing happens to the other two copies. If we put version numbers in the table above, we get:

   HEAD           index        work-tree
-----------    -----------    -----------
file.txt(1)     file.txt(1)   file.txt(2)

When you run git add file.txt, Git updates the index copy to match the work-tree copy:

   HEAD           index        work-tree
-----------    -----------    -----------
file.txt(1)     file.txt(2)   file.txt(2)

Note that you can change the work-tree copy again, without using git add, and at this point all three copies will differ.

(Note that if you run git add on a new file, that isn't in the index yet, Git will copy this new file into the index. This adds the new file to the proposed commit. It's not yet in any commit, but it's now ready to be committed. Or, you can run git rm on a file to remove it from both the index and your working tree. Now it's gone from the index, so it won't be in the next commit. This does not affect any existing commits: those cannot be changed.)

When you run git commit, this is what happens:

  1. Git gathers any metadata it needs, such as your name and email address, and the current date-and-time. It may collect a log message from you, or use the -m argument to get the log message.
  2. Git uses the current commit's hash ID to go into the metadata for the new commit.
  3. Git writes out whatever files are in the index.
  4. Git turns the above into a commit. This creates the commit's unique hash ID. (One reason for the date-and-time-stamp is that since this is always changing, the hash ID will differ from that of any other commit that is otherwise exactly the same.)
  5. This is the sneaky bit. Now that the new commit exists, Git writes the new commit's hash ID into the current branch name.

This means that if you currently have:

A--B--C   <-- master, seconde-branch (HEAD)

and you run git commit and it successfully makes a new commit, you now have:

A--B--C   <-- master
       \
        D   <-- seconde-branch (HEAD)

Note how master still points to commit C, but seconde-branch now points to new commit D. Commit D points back to existing commit C as its parent. No commits have changed, but there is now a new commit in the repository.

If you now run:

git checkout master     # or git switch master

Git must now remove the commit-D files and replace them with the commit-C files. Git has to do this for all the files that are different. It can cheat a bit, and for any file that is the same in commits C and D, it can leave that file alone in the index and working tree.

(A degenerate case of "leave the file alone" occurs when switching from commit C to commit C: there's no change at all, so all files can be left alone. That's the case you're seeing in your example, and it's always true for the kind of git checkout -b you are using.)

But if some files are different, Git will have to remove-and-replace those. Here Git will first make sure that these files in your working tree aren't changed; if they are, Git will refuse to switch commits. You can force the switch anyway, telling Git throw away my changes. (Since those changes are in your working tree, which is not in Git, Git will not be able to help you recover from this. So don't ignore Git's complaints about files that would be overwritten. Figure out why you haven't saved them!)

Let's switch to commit C again:

A--B--C   <-- master (HEAD)
       \
        D   <-- seconde-branch

We can now make a new commit on master, by changing some files, or adding new files, or removing files, or some combination of all three. We git add any updates if necessary and run git commit, and after it succeeds, we have a new commit, with a new big ugly hash ID, but we'll just call it E:

        E   <-- master (HEAD)
       /
A--B--C
       \
        D   <-- seconde-branch

Now, think about this: Which commits are on which branches? In particular, which branch(es) hold commits A-B-C? Remember that Git always starts with the last commits—of which there are now two, commits D and E—and works backwards.

Working backwards from E, we also traverse commits C, then B, then A. So these commits should all be on master. Working backwards from D, we also traverse C, then B, then A. So these commits should all be on seconde-branch.

So: which branch(es) are commits A-B-C on? I'll leave this as an exercise, but will note that Git's answer is very different from, say, Mercurial's.

uj5u.com熱心網友回復:

未提交的更改系結到任何分支。

它們只是本地檔案系統中的本地更改

當您在分支之間切換時,Git 通常會保留這些本地更改(除非您通過強制檢出來丟棄它們)。

如果您想存盤更改以備后用,但又不想將它們提交到任何分支,請使用git stash save -u將本地更改保存到本地 git stash。

然后您可以稍后使用 git stash apply

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

標籤:混帐

上一篇:Git:如果您克隆存盤庫,是否有內部注冊表?

下一篇:如何在單個gitrepo中擁有多個lambda函式并為其創建CI/CD管道

標籤雲
其他(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)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more