摘要:還可以通過檢查對象內(nèi)容的的哈希值和對象名是否相同,來判斷對象內(nèi)容是否正確。對象對象和其它所有的對象一樣,都用其內(nèi)容的哈希值來命名的只有當(dāng)兩個對象的內(nèi)容完全相同包括其所指向所有子對象時,它的名字才會一樣,反之亦然。
git是什么
簡單來說,Git,它是一個快速的 分布式版本控制系統(tǒng) (Distributed Version Control System,簡稱 DVCS) 。
同傳統(tǒng)的 集中式版本控制系統(tǒng) (Centralized Version Control Systems,簡稱CVCS) 不同,Git的分布式特性使得開發(fā)者間的協(xié)作變得更加靈活多樣。
這時候我們會想到:
什么又是版本控制呢?
什么是分布式什么是集中式?
我們帶著問題往下走。
版本控制版本控制是一種記錄一個或若干文件內(nèi)容變化,以便將來查閱特定版本修訂情況的系統(tǒng)。
比如:有一位程序員他可能需要保存一個代碼文件的所有的修訂版本,這樣就可以
將某個文件回溯到之前的狀態(tài)
甚至將整個項目都回退到過去某個時間點的狀態(tài)
比較文件的變化細(xì)節(jié),查出最后是誰修改了哪個地方,從而找出導(dǎo)致怪異問題出現(xiàn)的原因
這時候采用版本控制就是一個非常明智的選擇,使用版本控制系統(tǒng)通常還意味著,就算你亂來一氣把整個項目中的文件改的改刪的刪,你也照樣可以輕松恢復(fù)到原先的樣子。 但額外增加的工作量卻微乎其微。
版本控制的成長兒童:人們通過復(fù)制整個項目的方式來保存不同的版本,或許還會改名加上備份時間以示區(qū)別。好處就是簡單,但是特別容易犯錯,一不小心會寫錯文件或者覆蓋意想外的文件。
少年:人們?yōu)榱松厦娴膯栴},很久以前就開發(fā)了許多種本地版本控制系統(tǒng),大多是采用某種簡單的數(shù)據(jù)庫來記錄文件的歷次更新差異,比如其中比較流行的 RCS 。
青年:人們又遇到一個問題,如何讓在不同系統(tǒng)上的開發(fā)者協(xié)同工作? 于是,集中化的版本控制系統(tǒng)( CVCS)應(yīng)運而生。 這類系統(tǒng),諸如 CVS 、 Subversion ,都有一個單一的集中管理的服務(wù)器,保存所有文件的修訂版本,而協(xié)同工作的人們都通過客戶端連到這臺服務(wù)器,取出最新的文件或者提交更新?,F(xiàn)在,每個人都可以在一定程度上看到項目中的其他人正在做些什么。 而管理員也可以輕松掌控每個開發(fā)者的權(quán)限,并且管理一個 CVCS。
事分兩面,有好有壞。 這么做最顯而易見的缺點是中央服務(wù)器的單方面故障。 如果關(guān)機(jī)一小時,那么在這一小時內(nèi),誰都無法提交更新,也就無法協(xié)同工作。 如果中心數(shù)據(jù)庫所在的磁盤發(fā)生損壞,又沒有做恰當(dāng)備份,毫無疑問你將丟失所有數(shù)據(jù)——包括項目的整個變更歷史,只剩下人們在各自機(jī)器上保留的多帶帶快照。
壯年:于是分布式版本控制系統(tǒng)面世了。 在這類系統(tǒng)中,像 Git 、 Mercurial 等,客戶端并不只提取最新版本的文件快照,而是把代碼倉庫完整地鏡像下來。 這么一來,任何一處協(xié)同工作用的服務(wù)器發(fā)生故障,事后都可以用任何一個鏡像出來的本地倉庫恢復(fù)。 因為每一次的克隆操作,實際上都是一次對代碼倉庫的完整備份。
許多這類系統(tǒng)都可以指定和若干不同的遠(yuǎn)端代碼倉庫進(jìn)行交互。籍此,你就可以在同一個項目中,分別和不同工作小組的人相互協(xié)作。 你可以根據(jù)需要設(shè)定不同的協(xié)作流程,比如層次模型式的工作流,而這在以前的集中式系統(tǒng)中是無法實現(xiàn)的。
git誕生史記很多人都知道, Linus 在1991年創(chuàng)建了開源的 Linux ,從此,Linux 系統(tǒng)不斷發(fā)展,已經(jīng)成為最大的服務(wù)器系統(tǒng)軟件了。
Linus 雖然創(chuàng)建了 Linux,但 Linux 的壯大是靠全世界熱心的志愿者參與的,這么多人在世界各地為 Linux 編寫代碼,那 Linux 的代碼是如何管理的呢?
事實是,在2002年以前,世界各地的志愿者把源代碼文件通過 diff 的方式發(fā)給 Linus,然后由 Linus 本人通過手工方式合并代碼!
你也許會想,為什么 Linus 不把 Linux 代碼放到版本控制系統(tǒng)里呢?不是有 CVS、SVN這些免費的版本控制系統(tǒng)嗎?因為 Linus 堅定地反對 CVS 和 SVN,這些集中式的版本控制系統(tǒng)不但速度慢,而且必須聯(lián)網(wǎng)才能使用。有一些商用的版本控制系統(tǒng),雖然比 CVS 、 SVN 好用,但那是付費的,和 Linux 的開源精神不符。
不過,到了2002年,Linux 系統(tǒng)已經(jīng)發(fā)展了十年了,代碼庫之大讓 Linus 很難繼續(xù)通過手工方式管理了,社區(qū)的弟兄們也對這種方式表達(dá)了強(qiáng)烈不滿,于是 Linus 選擇了一個商業(yè)的版本控制系統(tǒng) BitKeeper,BitKeeper 的東家 BitMover 公司出于人道主義精神,授權(quán) Linux 社區(qū)免費使用這個版本控制系統(tǒng)。
安定團(tuán)結(jié)的大好局面在2005年就被打破了,原因是 Linux 社區(qū)牛人聚集,不免沾染了一些梁山好漢的江湖習(xí)氣。開發(fā) Samba 的 Andrew 試圖破解 BitKeeper 的協(xié)議(這么干的其實也不只他一個),被 BitMover 公司發(fā)現(xiàn)了(監(jiān)控工作做得不錯?。?,于是 BitMover 公司怒了,要收回 Linux 社區(qū)的免費使用權(quán)。
Linus 可以向 BitMover 公司道個歉,保證以后嚴(yán)格管教弟兄們,嗯,這是不可能的。實際情況是這樣的:
Linus 花了兩周時間自己用 C 寫了一個分布式版本控制系統(tǒng),這就是 Git!一個月之內(nèi),Linux 系統(tǒng)的源碼已經(jīng)由 Git 管理了!牛是怎么定義的呢?大家可以體會一下。
Git 迅速成為最流行的分布式版本控制系統(tǒng),尤其是2008年,GitHub 網(wǎng)站上線了,它為開源項目免費提供 Git 存儲,無數(shù)開源項目開始遷移至 GitHub,包括 jQuery,PHP,Ruby等等。
歷史就是這么偶然,如果不是當(dāng)年 BitMover 公司威脅 Linux 社區(qū),可能現(xiàn)在我們就沒有免費而超級好用的 Git 了。
git的優(yōu)點在集中式系統(tǒng)中,每個開發(fā)者就像是連接在集線器上的節(jié)點,彼此的工作方式大體相像。 而在 Git 中,每個開發(fā)者同時扮演著節(jié)點和集線器的角色——也就是說,每個開發(fā)者既可以將自己的代碼貢獻(xiàn)到其他的倉庫中,同時也能維護(hù)自己的公開倉庫,讓其他人可以在其基礎(chǔ)上工作并貢獻(xiàn)代碼。 由此,Git 的分布式協(xié)作可以為你的項目和團(tuán)隊衍生出種種不同的工作流程。
速度快
簡單的設(shè)計,易用
對非線性開發(fā)模式的強(qiáng)力支持(允許成千上萬個并行開發(fā)的分支)
完全分布式
有能力高效管理類似 Linux 內(nèi)核一樣的超大規(guī)模項目(速度和數(shù)據(jù)量)
git實現(xiàn)原理從根本上來講 Git 是一個內(nèi)容尋址 (content-addressable) 文件系統(tǒng),并在此之上提供了一個版本控制系統(tǒng)的用戶界面,Git 的核心部分是一個簡單的鍵值對數(shù)據(jù)庫 (key-value data store) 。 你可以向該數(shù)據(jù)庫插入任意類型的內(nèi)容,它會返回一個鍵值,通過該鍵值可以在任意時刻再次檢索 (retrieve) 該內(nèi)容。
初始化的git目錄當(dāng)在一個新目錄或已有目錄執(zhí)行 git init 時,Git 會創(chuàng)建一個 .git 目錄。 這個目錄包含了幾乎所有 Git 存儲和操作的對象。 如若想備份或復(fù)制一個版本庫,只需把這個目錄拷貝至另一處即可。
$ ls -F1 HEAD config* description hooks/ info/ objects/ refs/
這是一個全新的 git init 版本庫,這將是你看到的默認(rèn)結(jié)構(gòu)。
description 文件僅供 GitWeb 程序使用,我們無需關(guān)心。
config 文件包含項目特有的配置選項。
info 目錄包含一個全局性排除(global exclude)文件,用以放置那些不希望被記錄在 .gitignore 文件中的忽略模式(ignored patterns)。
hooks 目錄包含客戶端或服務(wù)端的鉤子腳本 (hook scripts)。
objects 目錄存儲所有數(shù)據(jù)內(nèi)容。
refs 目錄存儲指向數(shù)據(jù)(分支)的提交對象的指針
HEAD 文件指示目前被檢出的分支
index 文件保存暫存區(qū)信息。
git對象模型所有用來表示項目歷史信息的文件,是通過一個40個字符的 (40-digit) “對象名”來索引的,對象名看起來像這樣:
6ff87c4664981e4397625791c8ea3bbb5f2279a3
你會在Git里到處看到這種“40個字符”字符串。每一個“對象名”都是對“對象”內(nèi)容做 SHA1 哈希計算得來的,( SHA1 是一種密碼學(xué)的哈希算法)。這樣就意味著兩個不同內(nèi)容的對象不可能有相同的“對象名”。
這樣做會有幾個好處:
Git 只要比較對象名,就可以很快的判斷兩個對象是否相同。
因為在每個倉庫 (repository) 的“對象名”的計算方法都完全一樣,如果同樣的內(nèi)容存在兩個不同的倉庫中,就會存在相同的“對象名”下。
Git 還可以通過檢查對象內(nèi)容的 SHA1 的哈希值和“對象名”是否相同,來判斷對象內(nèi)容是否正確。
對象每個對象 (object) 包括三個部分:類型,大小和內(nèi)容。大小就是指內(nèi)容的大小,內(nèi)容取決于對象的類型,有四種類型的對象:"blob" 、 "tree" 、 "commit" 和 "tag" 。
“blob” 用來存儲文件數(shù)據(jù),通常是一個文件。
“tree” 有點像一個目錄,它管理一些“tree”或是 “blob”(就像文件和子目錄)。
一個“commit”只指向一個"tree",它用來標(biāo)記項目某一個特定時間點的狀態(tài)。它包括一些關(guān)于時間點的元數(shù)據(jù),如時間戳、最近一次提交的作者、指向上次提交 (commits) 的指針等等。
一個 “tag” 是來標(biāo)記某一個提交 (commit) 的方法。
幾乎所有的 Git 功能都是使用這四個簡單的對象類型來完成的。它就像是在你本機(jī)的文件系統(tǒng)之上構(gòu)建一個小的文件系統(tǒng)。
Blob對象一個 blob 通常用來存儲文件的內(nèi)容。
Tree 對象一個 tree 對象可以指向一個包含文件內(nèi)容的 blob 對象, 也可以是其它包含某個子目錄內(nèi)容的其它 tree 對象,它一般用來表示內(nèi)容之間的目錄層次關(guān)系。 Tree 對象、blob 對象和其它所有的對象一樣,都用其內(nèi)容的 SHA1 哈希值來命名的;只有當(dāng)兩個 tree 對象的內(nèi)容完全相同(包括其所指向所有子對象)時,它的名字才會一樣,反之亦然。這樣就能讓Git 僅僅通過比較兩個相關(guān)的 tree 對象的名字是否相同,來快速的判斷其內(nèi)容是否不同。
Commit對象commit 對象指向一個 tree 對象,并且?guī)в邢嚓P(guān)的描述信息。
一個提交 commit 由以下的部分組成:
一個 tree 對象:tree 對象的 `SHA1簽名, 代表著目錄在某一時間點的內(nèi)容。
父對象 (parent(s)): 提交 (commit) 的SHA1簽名代表著當(dāng)前提交前一步的項目歷史。合并的提交 (merge commits) 可能會有不只一個父對象。如果一個提交沒有父對象,那么我們就叫它“根提交" (root commit) ,它就代表著項目最初的一個版本 (revision)。 每個項目必須有至少有一個“根提交"(root commit)。
作者 (author) :做了此次修改的人的名字,還有修改日期。
提交者(committer):實際創(chuàng)建提交(commit)的人的名字, 同時也帶有提交日期。
注釋:用來描述此次提交。
注意:一個提交(commit)本身并沒有包括任何信息來說明其做了哪些修改; 所有的修改(changes)都是通過與父提交(parents)的內(nèi)容比較而得出的。 值得一提的是, 盡管git可以檢測到文件內(nèi)容不變而路徑改變的情況, 但是它不會去顯式(explicitly)的記錄文件的更名操作(可以看一下 git diff )。
一般用 git commit 來創(chuàng)建一個提交 (commit), 這個提交 (commit) 的父對象一般是當(dāng)前分支 (current HEAD) ,同時把存儲在當(dāng)前索引 (index) 的內(nèi)容全部提交。
對象模型:如果我們把它提交 (commit) 到一個 Git 倉庫中, 在 Git 中它們也許看起來就如下圖:
你可以看到:每個目錄都創(chuàng)建了 tree對象 (包括根目錄), 每個文件都創(chuàng)建了一個對應(yīng)的 blob對象。最后有一個 commit 對象 來指向根 tree 對象 (root of trees) , 這樣我們就可以追蹤項目每一項提交內(nèi)容.
標(biāo)簽對象:一個標(biāo)簽對象包括一個對象名(SHA1簽名), 對象類型, 標(biāo)簽名, 標(biāo)簽創(chuàng)建人的名字(tagger), 還有一條可能包含有簽名(signature)的消息.
回到我們的問題 強(qiáng)大的git分支有人把 Git 的分支模型稱為它的必殺技特性,也正因為這一特性,使得它 從眾多版本控制系統(tǒng)中脫穎而出。
Git 保存的不是文件的變化或者差異,而是一系列不同時刻的文件快照。
在進(jìn)行提交操作時,Git 會保存一個提交對象(commit object)。知道了 Git 保存數(shù)據(jù)的方式,該提交對象會包含一個指向暫存內(nèi)容快照的指針。 但不僅僅是這樣,該提交對象還包含了作者的姓名和郵箱、提交時輸入的信息以及指向它的父對象的指針。首次提交產(chǎn)生的提交對象沒有父對象,普通提交操作產(chǎn)生的提交對象有一個父對象,而由多個分支合并產(chǎn)生的提交對象有多個父對象,
當(dāng)使用 git commit 新建一個提交對象前,Git 會先計算每一個子目錄的校驗和(40 個字符長度 SHA-1 字串),然后在 Git 倉庫中將這些目錄保存為樹(tree)對象。之后 Git 創(chuàng)建的提交對象,除了包含相關(guān)提交信息以外,還包含著指向這個樹對象(項目根目錄)的指針,如此它就可以在將來需要的時候,重現(xiàn)此次快照的內(nèi)容了。
Git 中的分支,其實本質(zhì)上僅僅是個指向 commit 對象的可變指針。Git 會使用 master 作為分支的默認(rèn)名字。在若干次提交后,你其實已經(jīng)有了一個指向最后一次提交對象的 master 分支,它在每次提交的時候都會自動向前移動。
Git 是如何知道你當(dāng)前在哪個分支上工作的呢?其實答案也很簡單,它保存著一個名為 HEAD 的特別指針。在 Git 中,它是一個指向你正在工作中的本地分支的指針,我們可以將 HEAD 想象為當(dāng)前分支的別名。
由于 Git 中的分支實際上僅是一個包含所指對象校驗和的文件,所以創(chuàng)建和銷毀一個分支就變得非常廉價。說白了,新建一個分支就是向一個文件寫入 41 個字節(jié)(外加一個換行符)那么簡單,當(dāng)然也就很快了。
大多數(shù)版本控制系統(tǒng)它們管理分支大多采取備份所有項目文件到特定目錄的方式,所以根據(jù)項目文件數(shù)量和大小不同,可能花費的時間也會有相當(dāng)大的差別,快則幾秒,慢則數(shù)分鐘。
而 Git 的實現(xiàn)與項目復(fù)雜度無關(guān),它永遠(yuǎn)可以在幾毫秒的時間內(nèi)完成分支的創(chuàng)建和切換。同時,因為每次提交時都記錄了祖先信息(parent 對象),將來要合并分支時,尋找恰當(dāng)?shù)暮喜⒒A(chǔ)(譯注:即共同祖先)的工作其實已經(jīng)自然而然地擺在那里了,所以實現(xiàn)起來非常容易。Git 鼓勵開發(fā)者頻繁使用分支,正是因為有著這些特性作保障。
分支的新建與合并新建分支并進(jìn)入
$ git checkout -b iss53
根據(jù)需求寫代碼并提交
$ git commit -a -m "new text"
接到線上問題需要并且修改bug
$ git checkout master $ git checkout -b hotfix $ git commit -a -m "fixed bug"
合并修改完bug的代碼進(jìn)master(暫無沖突)
$ git checkout master $ git merge hotfix
解決問題后刪除hotfix分支并返回原來的iss53分支繼續(xù)工作
$ git branch -d hotfix $ git checkout iss53 $ git commit -a -m "finished"
合并iss53分支進(jìn)主分支
$ git checkout master $ git merge iss53
請注意,這次合并操作的底層實現(xiàn),并不同于之前 hotfix 的并入方式。因為這次你的開發(fā)歷史是從更早的地方開始分叉的。由于當(dāng)前 master 分支所指向的提交對象(C4)并不是 iss53 分支的直接祖先,Git 不得不進(jìn)行一些額外處理。就此例而言,Git 會用兩個分支的末端(C4 和 C5)以及它們的共同祖先(C2)進(jìn)行一次簡單的三方合并計算。
這次,Git 沒有簡單地把分支指針右移,而是對三方合并后的結(jié)果重新做一個新的快照,并自動創(chuàng)建一個指向它的提交對象(C6)。這個提交對象比較特殊,它有兩個祖先(C4 和 C5)。
有時候合并操作并不會如此順利。如果在不同的分支中都修改了同一個文件的同一部分,Git 就無法干凈地把兩者合到一起。如果你在解決問題 #53 的過程中修改了 hotfix 中修改的部分,將會出現(xiàn)問題。
Git 作了合并,但沒有提交,它會停下來等你解決沖突。
任何包含未解決沖突的文件都會以未合并 unmerged 的狀態(tài)列出。Git 會在有沖突的文件里加入標(biāo)準(zhǔn)的沖突解決標(biāo)記,可以通過它們來手工定位并解決這些沖突。
rebase 變基最容易的整合分支的方法是 merge 命令,它會把兩個分支最新的快照(C3 和 C4)以及二者最新的共同祖先(C2)進(jìn)行三方合并,合并的結(jié)果是產(chǎn)生一個新的提交對象(C5)。:
但是,如果你想讓 experiment分支歷史看起來像沒有經(jīng)過任何合并一樣,還有另外一個選擇:你可以把在 C3 里產(chǎn)生的變化補(bǔ)丁在 C4 的基礎(chǔ)上重新打一遍。在 Git 里,這種操作叫做變基 (rebase)。有了 rebase 命令,就可以把在一個分支里提交的改變移到另一個分支里重放一遍。
$ git checkout experiment $ git rebase master
它的原理是回到兩個分支最近的共同祖先,根據(jù)當(dāng)前分支(也就是要進(jìn)行變基的分支 experiment )后續(xù)的歷次提交對象(這里只有一個 C3),生成一系列文件補(bǔ)丁,然后以基底分支(也就是主干分支 master)最后一個提交對象(C4)為新的出發(fā)點,逐個應(yīng)用之前準(zhǔn)備好的補(bǔ)丁文件,最后會生成一個新的合并提交對象(C3"),從而改寫 experiment 的提交歷史,使它成為 master 分支的直接下游
簡單講他就是把你的 experiment 分支里的每個提交 commit 取消掉,并且把它們臨時 保存為補(bǔ)丁 patch (這些補(bǔ)丁放到".git/rebase"目錄中),然后把 experiment 分支更新 到最新的 origin 分支,最后把保存的這些補(bǔ)丁應(yīng)用到 experiment 分支上。
現(xiàn)在的 C3" 對應(yīng)的快照,其實和普通的三方合并,即上個例子中的 C5 對應(yīng)的快照內(nèi)容一模一樣了。雖然最后整合得到的結(jié)果沒有任何區(qū)別,但變基能產(chǎn)生一個更為整潔的提交歷史。如果視察一個變基過的分支的歷史記錄,看起來會更清楚:仿佛所有修改都是在一根線上先后進(jìn)行的,盡管實際上它們原本是同時并行發(fā)生的。
在 rebase 的過程中,也許會出現(xiàn)沖突 conflict。在這種情況,Git 會停止 rebase 并會讓你去解決 沖突;在解決完沖突后,用 git-add 命令去更新這些內(nèi)容的索引 index, 然后,你無需執(zhí)行 git-commit ,只要執(zhí)行:
$ git rebase --continue
這樣git會繼續(xù)應(yīng)用 apply 余下的補(bǔ)丁。在任何時候,你可以用 --abort 參數(shù)來終止 rebase 的行動,并且 experiment 分支會回到 rebase 開始前的狀態(tài)。
$ git rebase --abort
git merge 應(yīng)該只用于為了保留一個有用的,語義化的準(zhǔn)確的歷史信息,而希望將一個分支的整個變更集成到另外一個 branch 時使用 rebase。這樣形成的清晰版本變更圖有著重要的價值。
所有其他的情況都是以不同的方式使用 rebase 的適合場景:經(jīng)典型方式,三點式,interactive 和 cherry-picking。
我們使用變基的目的:是想要得到一個能在遠(yuǎn)程分支上干凈應(yīng)用的補(bǔ)丁 — 比如某些項目你不是維護(hù)者,但想幫點忙的話,最好用變基:先在自己的一個分支里進(jìn)行開發(fā),當(dāng)準(zhǔn)備向主項目提交補(bǔ)丁的時候,根據(jù)最新的 origin/master 進(jìn)行一次變基操作然后再提交,這樣維護(hù)者就不需要做任何整合工作(實際上是把解決分支補(bǔ)丁同最新主干代碼之間沖突的責(zé)任,化轉(zhuǎn)為由提交補(bǔ)丁的人來解決。),只需根據(jù)你提供的倉庫地址作一次快進(jìn)合并,或者直接采納你提交的補(bǔ)丁。
需要注意,合并結(jié)果中最后一次提交所指向的快照,無論是通過變基,還是三方合并,都會得到相同的快照內(nèi)容,只不過提交歷史不同罷了。變基是按照每行的修改次序重演一遍修改,而合并是把最終結(jié)果合在一起。
有趣的變基我在不同的topic之間來回切換,這樣會導(dǎo)致我的歷史中不同topic互相交叉,邏輯上組織混亂;
我們可能需要多個連續(xù)的commit來解決一個bug;
我可能會在commit中寫了錯別字,后來又做修改;
甚至我們在一次提交時純粹就是因為懶惰的原因,我可能吧很多的變更都放在一個commit中做了提交。
rebase可以合并commit
rebase可以用來修改commit信息
rebase可以用來拆分commit
git rebase -i HEAD~3
變基也可以放到其他分支進(jìn)行,并不一定非得根據(jù)分化之前的分支。
變基的風(fēng)險要用它得遵守一條準(zhǔn)則:
不要在公共分支上使用rebase。
“No one shall rebase a shared branch”?—?Everyone about rebase
如果你遵循這條金科玉律,就不會出差錯。
在進(jìn)行變基的時候,實際上拋棄了一些現(xiàn)存的提交對象而創(chuàng)造了一些類似但不同的新的提交對象。如果你把原來分支中的提交對象發(fā)布出去,并且其他人更新下載后在其基礎(chǔ)上開展工作,而稍后你又用 git rebase 拋棄這些提交對象,把新的重演后的提交對象發(fā)布出去的話,你的合作者就不得不重新合并他們的工作,這樣當(dāng)你再次從他們那里獲取內(nèi)容時,提交歷史就會變得一團(tuán)糟。
注意rebase往往會重寫歷史,所有已經(jīng)存在的commits雖然內(nèi)容沒有改變,但是commit本身的hash都會改變。
結(jié)論:只要你的分支上需要rebase的所有commits歷史還沒有被push過(比如上例中rebase時從分叉處開始有兩個commit歷史會被重寫),就可以安全地使用git rebase來操作。
上述結(jié)論可能還需要修正:對于不再有子分支的branch,并且因為rebase而會被重寫的commits都還沒有push分享過,可以比較安全地做rebase
思考下它的功能吧 git pull --rebase
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/94909.html
摘要:打開是個構(gòu)造函數(shù),定義了一些靜態(tài)屬性和方法我們先看在插件下地址上面寫的解釋就跟沒寫一樣在文件下我們看到輸出的一些對象方法每一個對應(yīng)一個模塊而在下引入的下面,我們先研究引入的對象的英文單詞解釋,除了最常用的點擊手勢之外,還有一個意思是水龍頭進(jìn) 打開compile class Compiler extends Tapable { constructor(context) { ...
摘要:淺析筆者在此整理了常見的命令,的重要性無需多言,與其再百度海中搜索命令,不妨嘗試收藏筆者的此篇作品。旨在快速高效地處理無論規(guī)模大小的任何軟件工程。其最大特色就是分支及合并操作非常快速簡便。 淺析git 筆者在此整理了常見的git命令,git的重要性無需多言,與其再百度海中搜索git命令,不妨嘗試收藏筆者的此篇作品。希望對你的學(xué)習(xí)有所幫助。 版本控制系統(tǒng)之git Git: (一)簡介:G...
摘要:淺析筆者在此整理了常見的命令,的重要性無需多言,與其再百度海中搜索命令,不妨嘗試收藏筆者的此篇作品。旨在快速高效地處理無論規(guī)模大小的任何軟件工程。其最大特色就是分支及合并操作非??焖俸啽?。 淺析git 筆者在此整理了常見的git命令,git的重要性無需多言,與其再百度海中搜索git命令,不妨嘗試收藏筆者的此篇作品。希望對你的學(xué)習(xí)有所幫助。 版本控制系統(tǒng)之git Git: (一)簡介:G...
摘要:淺析參數(shù)說明對于所有列表里提到的純模塊做處理需要在腳本里有一個包名到目錄的映射。闡明包名到目錄的映射,見鍵代表了包的名字,空的包名則代表不在任何包中的頂層包。最終會在下生成可執(zhí)行文件,調(diào)用制定的函數(shù)實例分析 python setup.py 淺析 setuptools.setup() 參數(shù)說明 packages 對于所有 packages 列表里提到的純 Python 模塊做處理 需要...
閱讀 2896·2021-11-17 09:33
閱讀 2292·2021-09-03 10:40
閱讀 603·2019-08-29 18:45
閱讀 3021·2019-08-29 16:21
閱讀 666·2019-08-29 11:11
閱讀 3451·2019-08-26 12:00
閱讀 3021·2019-08-23 18:19
閱讀 1152·2019-08-23 12:18