關于版本控制系統(tǒng)(即VCS:Version Control Systems)
歷程:什么是版本控制系統(tǒng)(VCS)?
墻薦:《Pro Git》中文版(實際上這本書已經夠了)
阮老師的:Git遠程操作詳解
Git之刪除本地倉庫
廖雪峰老師:Git教程
一些命令:
git init
創(chuàng)建一個空git倉庫或重新初始化現有的git倉庫
1.需要在本地內建倉庫,push到Git時刑然,使用git init初始化德玫,就可以變?yōu)?git的倉庫了孽水。初始化后苛秕,在當前目錄下會出現一個名為 .git 的目錄,所有 Git 需要的數據和資源都存放在這個目錄中纯陨。不過目前,僅僅是按照既有的結構框架初始化好了里邊所有的文件和目錄,但我們還沒有開始跟蹤管理項目中的任何一個文件翼抠。
git clone
將倉庫存儲到新目錄中
如果想對某個開源項目出一份力咙轩,可以先把該項目的 Git 倉庫復制一份出來,這就需要用到 git clone 命令阴颖。如果你熟悉其他的 VCS 比如 Subversion活喊,你可能已經注意到這里使用的是 clone 而不是 checkout。這是個非常重要的差別量愧,Git 收取的是項目歷史的所有數據(每一個文件的每一個版本)钾菊,服務器上有的數據克隆之后本地也都有了。實際上偎肃,即便服務器的磁盤發(fā)生故障煞烫,用任何一個克隆出來的客戶端都可以重建服務器上的倉庫,回到當初克隆時的狀態(tài)
git status
檢查當前文件狀態(tài)
git add .
跟蹤新文件
git diff
git commit
提交更新
還有很多命令累颂,這里就不不一一例舉了滞详。
開始使用Git
對于任何一個文件,在 Git 內都只有三種狀態(tài):已提交(committed)喘落,已修改(modified)和已暫存(staged)茵宪。已提交表示該文件已經被安全地保存在本地數據庫中了;已修改表示修改了某個文件瘦棋,但還沒有提交保存稀火;已暫存表示把已修改的文件放在下次提交時要保存的清單中。
由此我們看到 Git 管理項目時赌朋,文件流轉的三個工作區(qū)域:Git 的工作目錄凰狞,暫存區(qū)域,以及本地倉庫沛慢。
每個項目都有一個 Git 目錄(譯注:如果 git clone 出來的話赡若,就是其中 .git 的目錄;如果 git clone --bare 的話团甲,新建的目錄本身就是 Git 目錄逾冬。),它是 Git 用來保存元數據和對象數據庫的地方躺苦。該目錄非常重要身腻,每次克隆鏡像倉庫的時候,實際拷貝的就是這個目錄里面的數據匹厘。
從項目中取出某個版本的所有文件和目錄嘀趟,用以開始后續(xù)工作的叫做工作目錄。這些文件實際上都是從 Git 目錄中的壓縮對象數據庫中提取出來的愈诚,接下來就可以在工作目錄中對這些文件進行編輯她按。
所謂的暫存區(qū)域只不過是個簡單的文件牛隅,一般都放在 Git 目錄中。有時候人們會把這個文件叫做索引文件酌泰,不過標準說法還是叫暫存區(qū)域媒佣。
基本的 Git 工作流程如下:
在工作目錄中修改某些文件胀糜。
對修改后的文件進行快照夕春,然后保存到暫存區(qū)域。
提交更新狞甚,將保存在暫存區(qū)域的文件快照永久轉儲到 Git 目錄中授霸。
所以,我們可以從文件所處的位置來判斷狀態(tài):如果是 Git 目錄中保存著的特定版本文件际插,就屬于已提交狀態(tài)碘耳;如果作了修改并已放入暫存區(qū)域,就屬于已暫存狀態(tài)框弛;如果自上次取出后辛辨,作了修改但還沒有放到暫存區(qū)域,就是已修改狀態(tài)瑟枫。到第二章的時候斗搞,我們會進一步了解其中細節(jié),并學會如何根據文件狀態(tài)實施后續(xù)操作慷妙,以及怎樣跳過暫存直接提交僻焚。
配置用戶信息
第一個要配置的是你個人的用戶名稱和電子郵件地址。這兩條配置很重要膝擂,每次 Git 提交時都會引用這兩條信息虑啤,說明是誰提交了更新,所以會隨更新內容一起被永久納入歷史記錄:
$ git config --global user name "user name"
$ git config --global user email user@example.com
檢查已有的配置信息架馋,可以使用 git config --list
命令:
當不清楚命令時,可order help
接下來我們在Github上新建一個Repository
一般有兩種方法可以生成狞山,一種是直接在遠端生成,然后clone到本地(working directory)叉寂。另一種是在本地初始化好萍启,最后上傳到遠端(git directory)
遠端生成:
當你勾上Initialize this repository with a README選項時,倉庫自動生成
.git
文件屏鳍,此時才算是一個真正版本控制勘纯。
clone到本地
可以使用SSH方式,也可以使用HTTPS孕蝉,這里使用HTTPS屡律。
克隆倉庫的命令格式為
git clone [url]
這會在當前目錄下創(chuàng)建一個名為
Test
的目錄,其中包含一個 .git
的目錄降淮,用于保存下載下來的所有版本記錄超埋,然后從中取出最新版本的文件拷貝搏讶。如果進入這個新建的 Test
目錄,你會看到項目中的所有文件已經在里邊了霍殴,準備好后續(xù)的開發(fā)和使用媒惕。如果希望在克隆的時候,自己定義要新建的項目目錄名稱来庭,可以在上面的命令末尾指定新的名字:
這樣
clone
下來的就不是叫Test
了妒蔚,而是Mytest
檢查當前文件狀態(tài)
git status
說明現在的工作目錄相當干凈。換句話說月弛,所有已跟蹤文件在上次提交后都未被更改過肴盏。此外,上面的信息還表明帽衙,當前目錄下沒有出現任何處于未跟蹤的新文件菜皂,否則 Git 會在這里列出來。最后厉萝,該命令還顯示了當前所在的分支是 master恍飘,這是默認的分支名稱,實際是可以修改的谴垫,現在先不用考慮章母。
現在我們更改一下README文件
vim README.md
后,再次git status
此時翩剪,
Git
發(fā)現了我們修改的文件乳怎,但是,此時README
并沒被跟蹤肢专,所以需要手動跟蹤文件舞肆,Git也提示:(use "git add" and/or "git commit -a")
跟蹤新文件:git add
使用命令 git add 開始跟蹤一個新文件。所以博杖,要跟蹤 README 文件椿胯,運行:git add README
,也可以:git add .
加點表示剃根,Git會遞歸地將你執(zhí)行命令時所在的目錄中的所有文件添加上去哩盲,所以如果你將當前的工作目錄作為參數,它就會追蹤那兒的所有文件狈醉。
現在廉油,再次重申一下那幅圖,我修改了一點苗傅。
Git中的文件只有兩種狀態(tài)中的其中一種抒线,即不是已跟蹤就是未跟蹤,已跟蹤文件就是圖中藍色區(qū)域部分渣慕,可能是已修改嘶炭、未更新抱慌,或已放入暫存區(qū)。
git add所做的就是跟蹤文件眨猎,并放入暫存區(qū):
此時我們git commit,就會把暫存區(qū)內所有文件的更新情況睡陪,版本信息上傳至.git版本庫中了寺渗,這次版本更新就完成了。
但是兰迫,假設我們在commit之前修改了已跟蹤的README文件信殊,會發(fā)生什么呢?
查看狀態(tài)發(fā)現汁果, 文件出現了兩次鸡号!一次算未暫存,一次算已暫存须鼎。
實際上 Git 只不過暫存了你運行 git add 命令時的版本,如果現在提交府蔗,那么提交的是添加注釋前的版本晋控,而非當前工作目錄中的版本。所以姓赤,運行了 git add 之后又作了修訂的文件赡译,需要重新運行 git add 把最新版本重新暫存起來。
查看已暫存和未暫存的更新 git diff
實際上 git status 的顯示比較簡單不铆,僅僅是列出了修改過的文件蝌焚,如果要查看具體修改了什么地方,可以用 git diff 命令誓斥。稍后我們會詳細介紹 git diff只洒,不過現在,它已經能回答我們的兩個問題了:當前做的哪些更新還沒有暫存劳坑?有哪些更新已經暫存起來準備好了下次提交毕谴? git diff 會使用文件補丁的格式顯示具體添加和刪除的行。
要查看尚未暫存的文件更新了哪些部分距芬,不加參數直接輸入 git diff:
請注意涝开,單單 git diff 不過是顯示還沒有暫存起來的改動,而不是這次工作和上次提交之間的差異框仔。所以有時候你一下子暫存(git add)了所有更新過的文件后舀武,運行 git diff 后卻什么也沒有,就是這個原因离斩。
提交更新git commit
現在的暫存區(qū)域已經準備妥當可以提交了银舱。在此之前瘪匿,請一定要確認還有什么修改過的或新建的文件還沒有 git add 過,否則提交的時候不會記錄這些還沒暫存起來的變化纵朋。所以柿顶,每次準備提交前,先用 git status 看下操软,是不是都已暫存起來了嘁锯,然后再運行提交命令 git commit:
git commit
種方式會啟動文本編輯器以便輸入本次提交的說明。(默認會啟用 shell 的環(huán)境變量 $EDITOR 所指定的軟件聂薪,一般都是 vim 或 emacs家乘。當然也可以按照第一章介紹的方式,使用git config --global core.editor
命令設定你喜歡的編輯軟件藏澳。)
編輯器會顯示類似下面的文本信息(本例選用 Vim 的屏顯方式展示):
或者也可以使用git commit -m "XXX"
仁锯,-m 參數后跟提交說明的方式,在一行命令中提交更新:
好翔悠,現在你已經創(chuàng)建了第一個提交业崖!可以看到,提交后它會告訴你蓄愁,當前是在哪個分支(master)提交的双炕,本次提交的完整 SHA-1 校驗碼是什么(fbee2c0),以及在本次提交中撮抓,有多少文件修訂過妇斤,多少行添改和刪改過。
跳過使用暫存區(qū)域
盡管使用暫存區(qū)域的方式可以精心準備要提交的細節(jié)丹拯,但有時候這么做略顯繁瑣站超。Git 提供了一個跳過使用暫存區(qū)域的方式,只要在提交的時候乖酬,給 git commit 加上 -a 選項死相,Git 就會自動把所有已經跟蹤過的文件暫存起來一并提交,從而跳過 git add 步驟剑刑。
查看提交歷史:
在提交了若干更新之后媳纬,又或者克隆了某個項目,想回顧下提交歷史施掏,可以使用 git log 命令查看钮惠。
默認不用任何參數的話,git log 會按提交時間列出所有的更新七芭,最近的更新排在最上面素挽。看到了嗎狸驳,每次更新都有一個 SHA-1 校驗和预明、作者的名字和電子郵件地址缩赛、提交時間,最后縮進一個段落顯示提交說明撰糠。
關于遠程倉庫
查看當前的遠程庫
git remote
要查看當前配置有哪些遠程倉庫酥馍,可以用 git remote 命令,它會列出每個遠程庫的簡短名字阅酪。在克隆完某個項目后旨袒,至少可以看到一個名為 origin 的遠程庫,Git 默認使用這個名字來標識你所克隆的原始倉庫:
推送數據到遠程倉庫
項目進行到一個階段术辐,要同別人分享目前的成果砚尽,可以將本地倉庫中的數據推送到遠程倉庫。實現這個任務的命令很簡單: git push [remote-name] [branch-name]辉词。如果要把本地的 master 分支推送到 origin 服務器上(再次說明下必孤,克隆操作會自動使用默認的 master 和 origin 名字),可以運行下面的命令:git push origin master
如果瑞躺,在你推送到遠程之前有人在你的遠程倉庫上進行了修改敷搪,會出現什么呢?
現在我們將本地更新的數據跟蹤暫存幢哨,push到Remote Repository
可以看到购啄,有兩個操作未被跟蹤,未被暫存嘱么,也沒有進入本地版本庫中。現在我們將它們add并commit顽悼。
Updates were rejected because the remote contains work that you do
:大概意思(原諒我英語不好)就是遠程倉庫中包含了一些本地沒有的文件(更新)曼振。
此時,我們需要抓取遠程倉庫中的數據蔚龙,和本地同步之后冰评,再進行修改上傳。
從遠程倉庫抓取數據
git pull origin master
使用 git pull 命令自動抓取數據下來木羹,然后將遠端分支自動合并到本地倉庫中當前分支
pull回來之后甲雅,用vim編輯器打開,就可以看到坑填,遠程倉庫的文件和本地文件更新的區(qū)別抛人。
稍作改動后,我們保存脐瑰,就可以commit妖枚,push到遠程了。
本地創(chuàng)建倉庫并初始化
有兩種取得 Git 項目倉庫的方法苍在。第一種是在現存的目錄下绝页,通過導入所有文件來創(chuàng)建新的 Git 倉庫荠商。第二種是從已有的 Git 倉庫克隆出一個新的鏡像倉庫來。
在工作目錄中初始化新倉庫
git init
關于簡單的分支概念
當多人協同工作续誉,來開發(fā)莱没、維護一個項目時,包含ABC三個模塊(功能)酷鸦,程序員No.1—A饰躲,程序員No.2—B,程序員No.3—C井佑。一號程序員就可以從初始項目上拉一個新分支開發(fā)A模塊属铁,同樣的2、3號程序員也可以拉取屬于自己的開發(fā)分支躬翁,此時焦蘑,誰先完成了自己的開發(fā)任務,就可以直接合并到舊的項目中盒发,不斷迭代......
或者當一個線上項目出現問題例嘱,開發(fā)者可以返回服務器所在的分支,并開辟一個新的修復分支宁舰,當修復好以后拼卵,再把修復分支合并進來,再推送到服務器上.......
不是很準確的描述蛮艰,但這正是Git最強大的地方腋腮。
查看所有分支git branch -a
藍色:本地分支
紅色:遠程分支
* :當前所處分支
新建分支git branch
切換分支:
查看Dev分支內部文件,可以發(fā)現是和master分支是一樣的壤蚜。
現在我們模擬一下即寡,有人在新分支內進行更新:
加入了新文件,并跟蹤暫存袜刷,提交聪富。
在切回原分支master上(想象成一個樹干和樹枝會更形象):
可以看到,master分支上并沒有index.html文件著蟹,這可是同一個文件夾下哦墩蔓。
這就是分支簡單概念。
現在需要推送這個新分支了萧豆。
有時候可能需要你更改上傳倉庫URL奸披。
可以想象一下,master是線上版本涮雷,拉一個Dev分支后源内,進行開發(fā),測試。無誤后膜钓,我們需要將Dev分支合并到原master上嗽交,如何合并呢?
首先切換到需要合并的分支上颂斜,這里是master分支夫壁,然后使用git merge
命令
此時,master分支內沃疮,也有index.html文件了盒让。
再git push一次,此時就可以發(fā)布上線了司蔬,依舊是master分支邑茄,這個版本。
PS:之前對origin俊啼、master這兩個概念搞不清肺缕,現在倒是清晰了一些,origin就是這個repository默認名字授帕,默認遠端庫的名字同木。可以理解為一個指針跛十,當然也可以更改彤路,而master就是這個代碼庫的一個分支。
來自知友更正確的回答
沖突
有時候合并操作并不會如此順利芥映。如果在不同的分支中都修改了同一個文件的同一部分(例舉問題洲尊,實際可能沒那么簡單),Git 就無法干凈地把兩者合到一起(譯注:邏輯上說奈偏,這種問題只能由人來裁決颊郎。)
現在有人修改了master分支上的README。
這時霎苗,我們在本地更改了Dev分支,重新add榛做,commit唁盏,并push。
本地下检眯,更改Dev分支README文件厘擂,并add,commit锰瘸。切換到master分支后刽严,將Dev分支合并到master里,使得兩個分支內容一樣避凝,最后add舞萄,commit眨补,push。
出現了問題倒脓,遠程包含了一些本地沒有的內容撑螺,Git需要你手動解決這些矛盾。
那就git pull
唄
Git 作了合并崎弃,但沒有提交甘晤,它會停下來等你解決沖突。要看看哪些文件在合并時發(fā)生沖突饲做,可以用 git status 查閱:
任何包含未解決沖突的文件都會以未合并(unmerged)的狀態(tài)列出线婚。Git 會在有沖突的文件里加入標準的沖突解決標記,可以通過它們來手工定位并解決這些沖突盆均∪祝可以看到此文件包含類似下面這樣的部分:
可以看到 ======= 隔開的上半部分,解決沖突的辦法無非是二者選其一或者由你親自整合到一起缀踪。
最后整理好后居砖,記得
git add .
push后,遠端倉庫也做了更新驴娃。
PS:注意到奏候,之前的沖突時的push,藍色字體時MERGING唇敞,表明這實際上做了merge處理蔗草?(求大神告知)。
可以自己做更多的嘗試疆柔,本地修改咒精,遠端修改,不同分支處理旷档,就當是自己制造麻煩模叙,然后尋找方法,這是最好的嘗試了鞋屈。
在《Pro Git》文檔中也有這樣的說明:
遇到沖突時的分支合并
引發(fā)沖突的場景還有很多范咨,遇見更多的問題,并解決厂庇,才能更好的理解這一概念渠啊,使用好這一工具。
這篇文章只是很簡單的入門了一下Git权旷,當做自己的學習點滴紀錄替蛉,Keep moving吧~!