主頁 > 軟體工程 > 將新代碼簽入空的Bitbucket存盤庫時如何解決Git合并沖突

將新代碼簽入空的Bitbucket存盤庫時如何解決Git合并沖突

2022-03-02 02:48:55 軟體工程

在我發布我的問題之前,我想提一下我在另一個 Stack Exchange 網站上問過這個問題,并被告知這個問題需要在 Stack Overflow 中提出。

我最近在 Bitbucket 中創建了一個新存盤庫,我打算在其中簽入一個我已經從事了一段時間的新專案。當我在 Bitbucket 中創建新專案時,我選擇了包含.gitignore檔案的選項。當我嘗試推送我的新專案時,它導致我無法解決與此檔案的沖突。目前,我的代碼卡在我的本地存盤庫中。


我試過的

  1. 我試圖將 .gitignore 標記為在 Eclipse 中合并。我收到此錯誤:無法拉入狀態為: MERGING 的存盤庫然后我按照Stack Overflow answer中的建議執行了git merge --abort
error: Entry '.gitignore' not uptodate. Cannot merge.
fatal: Could not reset index file to revision 'HEAD'.
  1. 出現上述錯誤后,我嘗試了硬重置(來自 Eclipse)。然后我再次嘗試中止(來自上面的第 1 項。這導致了以下錯誤:
fatal: There is no merge to abort (MERGE_HEAD missing).
  1. 然后,我嘗試從 Git Bash 中提取結果:
$ git pull
error: Pulling is not possible because you have unmerged files.
hint: Fix them up in the work tree, and then use 'git add/rm <file>'
hint: as appropriate to mark resolution and make a commit.
fatal: Exiting because of an unresolved conflict.
  1. 嘗試通過運行git rm .gitignore洗掉 .gitignore ,然后呼叫git pull我收到以下錯誤:
fatal: refusing to merge unrelated histories

As you can see, I tried to fix from Git Bash and from Eclipse, but I have not been able to make any progress. I don't care losing the information on the .gitignore file. I can always recreate the file. I just need to resolve this conflict by any means necessary so that I can push the stuff in my local repo to the remote one. I am at a loss.

uj5u.com熱心網友回復:

TL;博士

如果您只想覆寫.gitignoreon Bitbucket,請考慮使用git push --force完全丟棄初始 Bitbucket 提交。

如果您想保留該檔案,請將其從該提交中取出:

git show origin/master:.gitignore > ignore.bitbucket

例如,然后根據需要合并檔案,然后使用強制推送丟棄(單個)Bitbucket 提交。

這是問題的根源:

當我在 Bitbucket 中創建新專案時,我選擇了包含.gitignore檔案的選項。

Git 與檔案無關,因此不存盤檔案——至少在您可能想到的意義上不是。Git 是關于什么以及 Git 因此存盤的是commits1 提交——但不是分支名稱——可以通過祖先關聯:就像大多數人有兩個父母一樣,大多數提交都有一個父母。例如,一些提交可以是其他一些提交的偉大-偉大-偉大-孫子,或者兩個提交可能是兄弟姐妹(都具有相同的父級),或其他類似的關系。

(這些關系形成了一個有向無環圖DAG。特別是提交圖允許 Git 找到兩個分支提示提交的共同祖先。)

提交本身,我們讓 Git 通過它們的哈希 ID 找到,每個都包含兩件事:

  • 每個提交都以壓縮和只讀格式保存每個檔案的完整快照,其中內容已洗掉重復(跨所有提交)。這些快照就像 tar 或 rar 或 winzip 檔案;需要先提取它們,然后才能實際使用檔案(然后提取的檔案此時不在 Git中,盡管在 Git中顯然有一個副本它只是存盤在這個壓縮和去重的 Git-ified格式)。

  • 每個提交還存盤一些元資料,或有關提交的資訊。例如,元資料包括提交人的姓名和電子郵件地址,以及顯示他們何時提交的日期和時間戳。在這個元資料中,為了自己的提交圖目的,Git 添加了先前提交串列的原始哈希 ID——通常只有一個,因此 Git 必須一次向后走一個提交,從最新提交到第二個提交-latest,到第三個最新,依此類推。

用戶當然想要他們的檔案。這些檔案在提交中,在它們永久存盤的檔案中。因此,我們必須選擇一些提交并讓 Git 提取該提交,以便我們可以查看和處理一些檔案。

If you have Bitbucket (or any other web hosting site) make a new, totally-empty repository, it will have no commits in it yet. That's fine, but if and when you clone this empty repository, you will get a warning: Git will say that there was nothing for it to check out (which is true!). This means if you make your own new, totally-empty repository, your new empty repository has the same lack-of-commits as your Bitbucket repository: the two are completely identical, in that both have nothing at all.

You can then make your own first commit, in your own repository, on your laptop or wherever it is stored. Being the first commit ever, this commit will have no parent commit. It can't have a parent, as there is no earlier commit, so it doesn't have a parent, and everything is fine. This commit is slightly special though, and Git will tell you that you have made a—or "the"—root commit:

$ git commit -m initial
[master (root-commit) c5f8984] initial
 1 file changed, 1 insertion( )
 create mode 100644 README.txt

But you didn't do that: you had Bitbucket create a repository and then create its own root commit in that repository, so that their repository is not empty. Their first commit contains a .gitignore file (and perhaps nothing else, or perhaps a README and/or LICENSE file; those are the typical GitHub options).

If you go on and make a root commit in your own initially-empty new repository, these two root commits are not related. They are not parent-and-child. They are not siblings, with a common parent. They are completely unrelated.

I use the terms your Git and their Git as shorthand here to refer to your Git software working with your repository and their Git software working with their repository. When you cross-connect two Gits like this, one of them is a sender and one is a receiver, and the sender will send some or all of his commits to the receiver, if the receiver doesn't have them yet. That's how we synchronize two repositories, especially when one was a clone of the other at some point.

Cloning copies all of the commits (and none of the branches, sort of), so a clone made at some point in some repository's lifetime will start out with the same commits as the original, and any added commits will generally have some sort of ancestry-relationship. But again, this doesn't quite work with an empty repository, since there's no initial commit.

So, what happened in this case is that after you set up the remote, you had your Git call up their Git and get, from them, their root commit that contains a .gitignore file. Meanwhile you had your own root commit that contains a .gitignore file.

It's not clear to me exactly what happened in Eclipse (Eclipse has its own Java-based Git implementation that doesn't quite do the same things as the C based implementation you get with command-line Git from bash or other shells). However, it left you in a weird state, which you fixed up, sort of, with your git rm command. At this point git pull from bash ran:

  1. git fetch: any git pull always runs this first. This git fetch had nothing to do though, as you'd already obtained the Bitbucket root commit.
  2. git merge: the git pull command means—is shorthand for—run git fetch, then run a second Git command and the default second Git command is git merge.

For git merge to work, it needs to find the best common ancestor between two tip commits. To describe this properly we need some annotations.


1More precisely, a Git repository consists of two databases, one holding commits and other internal Git objects, and one holding names. The two databases are simple key-value stores, with the objects database keyed by hash ID, allowing Git to retrieve the raw object contents by hash ID, and the names database pairing individual refs—branch names, tag names, and other such names—with a single hash ID.


Drawing branches in Git

As I mentioned above, each commit is a two-part entity, holding metadata (information about the commit) and data (the snapshot archive, in the Git-ified format). Each commit has a unique2 hash ID. To draw this, in a format suitable for human comprehension, we need to drop a lot of irrelevant detail, keeping just two things:

  • a name for each commit, and
  • the arrows coming out of the commit that form the arcs in the directed graph.

The result very often looks something like this:

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

where H, on the right, stands in for our latest commit's hash ID. Commit H has metadata that include the raw hash ID of an earlier commit, which we'll call G. Commit G has metadata with the hash ID of still-earlier commit F, and so on. By holding each previous-commit hash ID, the commit can be said to "point to" the earlier commit.

To quickly find any particular commit—in our case, our latest commit H—Git uses a branch name like master or main, or a tag name like v1.2, or some other name like origin/master. This name contains the raw hash ID of the actual commit, so it too can be said to "point to" a commit:

...--G--H   <-- main

What makes a branch name special in Git is that you can check out or switch to some branch so as to extract the files from its latest commit. Running git switch main here tells Git that you'd like to have, to see and work on/with, the contents of the files as they exist saved forever in commit H. Git therefore extracts those files to a work area—your working tree—and, as soon as it has done that, remembers which branch name you asked for. To remember the branch name, Git attaches the special name HEAD, which I draw like this:

...--G--H   <-- main (HEAD)

You can create new branch names at any time. Each name must point to exactly one commit. If you were to pick commit G, for instance, to create the new name br1, we would draw it this way:

...--G   <-- br1
      \
       H   <-- main (HEAD)

We're still "on" branch main, and still using the files from commit H, but now there's a direct way to find the hash ID of earlier commit G, rather than, e.g., running git log and finding the hash ID of G manually. But most often, when we create a new branch name, we make it point to the current commit:

...--G--H   <-- br1, main (HEAD)

We can now switch to that branch with git switch br1. This attaches our HEAD to the name br1, and extracts the files from H—except we already have all the files from H, so Git doesn't bother doing anything at all, other than shuffling the attachment of HEAD here:

...--G--H   <-- br1 (HEAD), main

If we now create a new commit, the new commit gets a new, unique hash ID. We will call it "commit I" for simplicity. New commit I will point back to the commit we were using when we made new commit I, i.e., commit H, and once Git has saved away all the files and metadata for new commit I, Git will write I's hash ID into the name to which HEAD is attached:

          I   <-- br1 (HEAD)
         /
...--G--H   <-- main

If we make another new commit J, J will point backwards to I, and Git will write J's hash ID into br1:

          I--J   <-- br1 (HEAD)
         /
...--G--H   <-- main

If we now switch back to main, Git will remove, from our work area, the files that go with J, and put in the files that go with H instead, and leave us with this:

          I--J   <-- br1
         /
...--G--H   <-- main (HEAD)

We can now create and switch to a new branch br2:

          I--J   <-- br1
         /
...--G--H   <-- br2 (HEAD), main

and as we make more commits, now br2 will get updated:

          I--J   <-- br1
         /
...--G--H   <-- main
         \
          K--L   <-- br2 (HEAD)

That, in a nutshell, is how Git branches really work: we add commits to them and they grow, and the branch name always means the last commit on the branch.

Git allows us to move, or even delete, any branch name at any time (although you're not allowed to delete the one HEAD is attached-to; you have to switch away from it first). If we move the name br2 back one step to commit K, we get:

          I--J   <-- br1
         /
...--G--H   <-- main
         \
          K   <-- br2 (HEAD)
           \
            L   ???

We won't look at how we do this, here, we'll just note that commit L still exists—but now you can't find it, unless you memorized its random-looking hash ID.3


2The unique hash ID is the real key to making Git work. The hash ID is unique across every commit in every repository, so that if two Gits meet, and compare hash IDs, they have the same hash ID if and only if they have the same commit, which they must have gotten by fetching or pushing (or during the initial clone, which is mostly one big fetch).

3Git has ways to get commit L back again, but if you leave it unreachable like this for more than a month or so, Git may get around to deciding that you don't care about it, and remove it for real. So commits are not always forever, but removing them is tricky: you arrange for Git not to see them—to have no names that let you and Git find them—and then eventually they will go away, unless they got sent to some other Git that decides to hang on to them.

Because Git is very greedy for new commits, once you've sent a commit somewhere else, it is very hard to get rid of for real. If you think of commits like viruses for which there is no vaccine, you're not far off. ??


Merging

Git has a lot of things that git merge will do that aren't merges, but to understand them and Git, it's best to start with the kind of git merge that is a full-blown merge. Suppose we have:

          I--J   <-- br1 (HEAD)
         /
...--G--H
         \
          K--L   <-- br2

from before. We're on br1, using commit J—our working tree has the files from J—and we decide we'd like to combine our work on br1 with the work someone did—maybe that was us, maybe it was someone else; Git won't really care, as Git only cares about commits. So we run:

git merge br2

Git will find not one or two but three commits. Git starts with our current commit J, which is easy to find: read HEAD, look up the branch name, that's the hash ID, and with the other commit we mention, which is also easy to find: see the name br2, look up the branch name, that gives hash ID L. So J and L are the two tip commits to merge.

But: in order to find work done, Git has a bit of a problem. Commits hold snapshots. To see changes, Git has to compare two snapshots. What snapshots can Git compare? Some people think Git will compare J and L directly, but that doesn't work. Suppose some file in J is different from its counterpart in L. Did we change it, or did they change it? Or maybe we both changed it. We're back to that question of what the heck does it mean to change a file when all the commits hold snapshots.

But suppose we work backwards from J. Moving back one hop we find commit I, which isn't on branch br2, but moving back two hops we find commit H, which is on br2. Likewise, moving back two hops from L, we land on H, which is on br1. So commit H is on both branches. That makes it a candidate. Git uses a particular algorithm here to find the best merge base commit,4 and in this case, always finds H.

Git then runs two diff operations, one from H to J to find out what we changed, and one from H to L to find out what they changed. The two diffs tell Git which lines of which files we changed, and which lines of which files they changed. By adding these two sets of changes together, Git may—and often is—able to combine the changes. Git then applies the combined changes to the files in the merge base. Depending on how you like to look at it, this keeps our changes while adding theirs, or keeps their changes while adding ours.

If Git is able to do this combining all on its own, git merge will make a new commit as usual, with one special feature. The new commit will have a snapshot as usual. It will have metadata as usual as well, listing us as the author and committer and "now" as the date-and-time-stamps. The merge commit can have a log message where we explain why we made the merge, and the merge commit has a list of previous commit hash IDs. Once the new merge commit is written out, Git updates the current branch name as usual, too.

The only thing special about this new merge commit is that its list of previous commits doesn't just list the current commit J. It also lists the commit we said to merge, i.e., commit L. So the updated graph looks like this:

          I--J
         /    \
...--G--H      M   <-- br1 (HEAD)
         \    /
          K--L   <-- br2

That's the basics of git merge. (All the complications come in with things like merge conflicts, and options that tell Git not to actually merge after all, or force Git to do a real merge even if Git would default to not bothering to merge. We won't cover any of this here.)


4The algorithm in question is the Lowest Common Ancestor one, modified for directed graphs. There may be multiple LCAs in some complex graphs; this answer does not cover this case.


Your case gives Git heartburn because of disjoint subgraphs

In your case, you have, in your own repository, one or more commits—I'll just draw one—and a branch name pointing to the last of these:

A   <-- main (HEAD)

plus one more commit obtained from the Bitbucket Git, with a remote-tracking name (origin/main or origin/master; I'm using main here):

B   <-- origin/main

You're now asking Git to combine these two root commits:

A   <-- main (HEAD)

B   <-- origin/main

Git works backwards from A and ... oops, there's nothing there. Git works backwards from B and, again, oops! There is no best common ancestor.

The output from git merge, at this point, is:

fatal: refusing to merge unrelated histories

because there's no common ancestor.

Git used to just fake one up (in Git versions before 2.9).5 If Git simply pretends that there's a common pre-root commit ε and makes things look like this:

  A   <-- main (HEAD)
 /
ε
 \
  B   <-- origin/main

then suddenly the general merge algorithm works. But what files are in this fake epsilon-commit ε? The answer is: none at all. That means that each file in A is completely new, and each file in B is also completely new. You'll often get an "add/add conflict" from this kind of merge and have to resolve the conflict manually.

To tell Git that you'd like to do that, use the --allow-unrelated-histories option to git merge. This emulates the pre-2.9 behavior. Once you resolve any conflicts, if needed, and finish the merge, you end up with a graph like this:

A--C   <-- main (HEAD)
  /
 B   <-- origin/main

which has two root commits. Commits A and B remain unrelated, but commit C has two parents, A and B, and hence you can git push commit C to a repository that has its own main pointing to commit B.

There's nothing good about having two root commits in a repository. It's not wrong, but it may confuse those who are not up on their graph theory. It's probably best to avoid this as long as it's easy, and give the description of your initial setup, it is easy.


5My guess here is that Eclipse is doing this too, so that you didn't get an "unrelated histories" error in Eclipse, but instead got some merge conflict(s). You might also not have made your own root commit yet, at that point.

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

標籤:git merge bitbucket

上一篇:gitpush-uorigin和gitpush--set-upstreamorigin有什么區別

下一篇:Git預提交客戶端鉤子。強制通過強制添加檔案

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

熱門瀏覽
  • Git本地庫既關聯GitHub又關聯Gitee

    創建代碼倉庫 使用gitee舉例(github和gitee差不多) 1.在gitee右上角點擊+,選擇新建倉庫 ? 2.選擇填寫倉庫資訊,然后進行創建 ? 3.服務端已經準備好了,本地開始作準備 (1)Git 全域設定 git config --global user.name "成鈺" git c ......

    uj5u.com 2020-09-10 05:04:14 more
  • CODING DevOps 代碼質量實戰系列第二課,相約周三

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。**《DevOps 代碼質量實戰(PHP 版)》**為 CODING DevOps 代碼質量實戰系列的第二課,同時也是本系列的 PHP ......

    uj5u.com 2020-09-10 05:07:43 more
  • 推薦Scrum書籍

    推薦Scrum書籍 直接上干貨,推薦書籍清單如下(推薦有順序的哦) Scrum指南 Scrum精髓 Scrum敏捷軟體開發 Scrum捷徑 硝煙中的Scrum和XP : 我們如何實施Scrum 敏捷軟體開發:Scrum實戰指南 Scrum要素 大規模Scrum:大規模敏捷組織的設計 用戶故事地圖 用 ......

    uj5u.com 2020-09-10 05:07:45 more
  • CODING DevOps 代碼質量實戰系列最后一課,周四發車

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。 **《DevOps 代碼質量實戰(Java 版)》**為 CODING DevOps 代碼質量實戰系列的最后一課,同時也是本系列的 ......

    uj5u.com 2020-09-10 05:07:52 more
  • 敏捷軟體工程實踐書籍

    Scrum轉型想要做好,第一步先了解并真正落實Scrum,那么我推薦的Scrum書籍是要看懂并實踐的。第二步是團隊的工程實踐要做扎實。 下面推薦工程實踐書單: 重構:改善既有代碼的設計 決議極限編程 : 擁抱變化 代碼整潔代碼 程式員的職業素養 修改代碼的藝術 撰寫可讀代碼的藝術 測驗驅動開發 : ......

    uj5u.com 2020-09-10 05:07:55 more
  • Jenkins+svn+nginx實作windows環境自動部署vue前端專案

    前面文章介紹了Jenkins+svn+tomcat實作自動化部署,現在終于有空抽時間出來寫下Jenkins+svn+nginx實作自動部署vue前端專案。 jenkins的安裝和配置已經在前面文章進行介紹,下面介紹實作vue前端專案需要進行的哪些額外的步驟。 注意:在安裝jenkins和nginx的 ......

    uj5u.com 2020-09-10 05:08:49 more
  • CODING DevOps 微服務專案實戰系列第一課,明天等你

    CODING DevOps 微服務專案實戰系列第一課**《DevOps 微服務專案實戰:DevOps 初體驗》**將由 CODING DevOps 開發工程師 王寬老師 向大家介紹 DevOps 的基本理念,并探討為什么現代開發活動需要 DevOps,同時將以 eShopOnContainers 項 ......

    uj5u.com 2020-09-10 05:09:14 more
  • CODING DevOps 微服務專案實戰系列第二課來啦!

    近年來,工程專案的結構越來越復雜,需要接入合適的持續集成流水線形式,才能滿足更多變的需求,那么如何優雅地使用 CI 能力提升生產效率呢?CODING DevOps 微服務專案實戰系列第二課 《DevOps 微服務專案實戰:CI 進階用法》 將由 CODING DevOps 全堆疊工程師 何晨哲老師 向 ......

    uj5u.com 2020-09-10 05:09:33 more
  • CODING DevOps 微服務專案實戰系列最后一課,周四開講!

    隨著軟體工程越來越復雜化,如何在 Kubernetes 集群進行灰度發布成為了生產部署的”必修課“,而如何實作安全可控、自動化的灰度發布也成為了持續部署重點關注的問題。CODING DevOps 微服務專案實戰系列最后一課:**《DevOps 微服務專案實戰:基于 Nginx-ingress 的自動 ......

    uj5u.com 2020-09-10 05:10:00 more
  • CODING 儀表盤功能正式推出,實作作業資料可視化!

    CODING 儀表盤功能現已正式推出!該功能旨在用一張張統計卡片的形式,統計并展示使用 CODING 中所產生的資料。這意味著無需額外的設定,就可以收集歸納寶貴的作業資料并予之量化分析。這些海量的資料皆會以圖表或串列的方式躍然紙上,方便團隊成員隨時查看各專案的進度、狀態和指標,云端協作迎來真正意義上 ......

    uj5u.com 2020-09-10 05:11:01 more
最新发布
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:41:12 more
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:35:34 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:05:44 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:00:18 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:20:31 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:55 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:18:51 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:00 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:17:55 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:12:06 more