本文轉載自:使用git和github管理自己的項目---基礎操作學習,進行了重新排版。二次轉載請注明原作出處。
我是通過看廖雪峰的git教程學習的,真的是極好的,以下是我學習過程中的總結,記錄下來,方便自己參考以熟悉git和github的使用。
除了廖雪峰的教程,還比較推薦在看完廖雪峰的教程之后,再看這樣一篇文章:使用git和github進行協同開發流程,和我的另一篇git的筆記:使用git和github管理自己的項目---真實開發環境的策略 ,深入了解github和git怎么在具體的項目開發中管理項目、有什么好的規范!
我這里記錄git的學習筆記,方便隨時參考,具體的git的原理、github的原理、集中式和分布式版本控制的區別、版本控制的概念和原理、Git和其他版本控制工具比如SVN的區別、以及更多的相關概念講解,請自己參見廖雪峰的git教程。
我強烈推薦先看廖雪峰的git教程來系統化認識和學習git,然后自己整理一份具體的步驟方便平時開發時快速參考,或者直接參考我的。
先說一個比較好笑的事:廖雪峰的git教程中,剛開始的部分的瀏覽量有38萬,但是最后一頁教程的網頁的瀏覽量是1萬多。
以前因為覺得git、github比較難,所以一直拖著不學,現在去嘗試學習,一晚上就OK了
- 重點之一是找到全面的、詳細的、生動的、高質量的教程。廖雪峰的git教程是我目前找到的最好的一個。之前找到的講解git用法的書《pro git》現在看來是沒有必要再看了!
- 重點之二就是自己立即去學,其實沒什么難的,不要被貌似難的表象、概念唬住。
- 重點之三是最好能自己做簡單的、系統的整理,方便自己隨時再回來查看、復習、參考,不至于出現這樣的情況:學完以后過一段時間之后再用,但是這時候發現忘了差不多了!
- 重點之四就是立即動手去用,否則學完很快就忘了。
有錢的買mac,沒錢的用ubuntu--或者其他的linux發行版、被逼無奈的用Windows--但是被逼之余的自主時間一定要遠離Windows。
現在我的測試環境是ubuntu。
以對一個文件的管理為例,簡單說明git的使用。另外需要說明的是下面的實驗過程主要是只針對一個文件、并且修改的次數往往只有一次,而在真正的項目中,往往有大量的文件,也可能多次修改后才合并,合并時候的沖突可能也不只一兩個,等等。不過原理都是一樣的,我想說的是,不要局限在這個教程的示例上,請自己通過教程掌握基本的遠原理之后,自己推廣、去大量的實踐,最重要的是要制定一個好的版本控制的策略(合理分工、安排,還是盡可能的避免沖突為好),這個可以參考:使用git和github進行協同開發流程以及我的學習筆記使用git和github管理自己的項目---真實開發環境的策略。
1.創建版本庫
-
sudo apt-get install git
先安裝git - 先創建目錄,作為倉庫
-
git init
初始化倉庫,可以發現當前目錄下多了一個.git的目錄,這個目錄是Git來跟蹤管理版本庫的,沒事千萬不要手動修改這個目錄里面的文件,不然改亂了,就把Git倉庫給破壞了 -
vim readme.txt
新建一個文本文件,比如往里面添加簡單的一行字符串 -
git add readme.txt
添加一個文件,比如readme.txt,如果目錄里面的所有文件都要添加,可以git add *
-
git commit-m "添加一個readme.txt文件"
將文件提交到倉庫,并加上說明(這時候是版本1)
如果是第一次使用git,那么git commit
可能報錯,所以需要你配置一些個人信息 -
git config --global user.email "you@example.com"
配置郵件 -
git config --global user.name "Your Name"
配置用戶名 - 必須配置,否則后面的commit、push到遠程庫都會失敗
- 然后再次
git commit -m "添加一個readme.txt文件"
才會成功
2.提交修改
- 假如此時第一次修改了readme.txt文件
-
git status
讓我們時刻掌握倉庫當前的狀態。這時告訴我們,readme.txt被修改過了,但還沒有準備提交的修改。 -
git diff readme.txt
查看對readme.txt做了什么修改 -
git add readme.txt
提交修改和提交新文件是一樣,先git add -
git status
可以再用git status查看倉庫的當前狀態,告訴我們,將要被提交的修改包括readme.txt - `git commit-m "第一次修改" 然后再git commit,并添加修改的描述(這時候是版本2)
-
git status
可以再執行git status看倉庫狀態,因為所有的都提交了,Git告訴我們當前沒有需要提交的修改,而且,工作目錄是干凈(working directory clean)的。
3.版本回退
- 你可以像上面所說的那樣不停的提交新的文件、提交對文件的修改
- 這時候第二次修改readme.txt文件
-
git add readme.txt
先git add -
git commit -m "第二次修改"
提交第二次修改(這時候是版本3) -
git log
顯示從最近到最遠的提交日志,具體顯示的內容自己試一試看看 -
git log --pretty=oneline
如果嫌輸出信息太多,看得眼花繚亂,試試加上--pretty=oneline參數 - 看這篇教程去理解為什么Git的版本號要這么長,Git的版本號類似:3628164fb26d48395383f8f31179f24e0882e1e0 這樣的特別長的十六進制數。
-
git reset --hard HEAD^
會回退到上一個版本,也就是從版本3回退到版本2 - 在Git中,用HEAD表示當前版本,也就是最新的提交3628164...882e1e0(注意我的提交ID和你的肯定不一樣),上一個版本就是HEAD,上上一個版本就是HEAD,當然往上100個版本寫100個比較容易數不過來,所以寫成HEAD~100
-
vim readme.txt
可以看到此時的readme.txt文件就是版本2時候的內容,回退成功! -
git log
此時看到版本3的信息沒有了 -
git reset --hard 3628164
通過命令行上的歷史信息(假如你沒清屏的話),找到版本3 的版本號,不一定要全部的版本號,就像這個命令的例子,只要前面的約7、8位這樣就可以指定回到版本3 -
vim readme.txt
看到的是第三版本的readme.txt文件的內容,所以又回來了 - Git的版本回退速度非常快,因為Git在內部有個指向當前版本的HEAD指針,當你回退版本的時候,Git僅僅是把HEAD從指向你要回退的那個版本
- `git reflog 記錄你的每一次命令,最先顯示的是這個命令執行之后的版本的版本號的前七位,這樣就算你清屏了或者重啟了,也能找到某個版本的版本號,就可以輕松回退到那個版本
4.工作區、版本庫和暫存區
工作區:就是你在電腦里能看到的目錄,比如我的learngit文件夾就是一個工作區。
版本庫:工作區有一個隱藏目錄.git,這個不算工作區,而是Git的版本庫。
暫存區:Git的版本庫里存了很多東西,其中最重要的就是稱為stage(或者叫index)的暫存區,還有Git為我們自動創建的第一個分支master,以及指向master的一個指針叫HEAD。
前面講了我們把文件往Git版本庫里添加的時候,是分兩步執行的:
- 第一步是用git add把文件添加進去,實際上就是把文件修改添加到暫存區;
- 第二步是用git commit提交更改,實際上就是把暫存區的所有內容提交到當前分支。
因為我們創建Git版本庫時,Git自動為我們創建了唯一一個master分支,所以,現在,git commit就是往master分支上提交更改。
你可以簡單理解為,需要提交的文件修改通通放到暫存區,然后,一次性提交暫存區的所有修改。
詳細知識見這篇教程。必須理解暫存區、工作區、版本庫。這些都是是Git非常重要的概念,弄明白了這些概念,就弄明白了Git的很多操作到底干了什么。沒弄明白的話,請反復看!!
5.管理修改
為什么Git比其他版本控制系統設計得優秀,因為Git跟蹤并管理的是修改,而非文件。
什么是修改?比如你新增了一行,這就是一個修改,刪除了一行,也是一個修改,更改了某些字符,也是一個修改,刪了一些又加了一些,也是一個修改,甚至創建一個新文件,也算一個修改。
通過實例講解什么叫跟蹤修改,要想理解,請參考原文結合暫存區的知識理解:
-
vim readme.txt
編輯文件,比如添加新的一行 -
git add readme.txt
添加,但是不提交 -
vim readme.txt
再編輯文件,比如再添加一行 -
git commit -m "修改兩次,添一次,提交一次"
提交 -
git status
看到的效果是:只提交了第一次的修改,第二次的修改沒有提交
那怎么提交第二次修改呢?你可以繼續git add
再git commit
,也可以別著急提交第一次修改,先git add
第二次修改,再git commit
,也就是第一次修改 -> git add -> 第二次修改 -> git add -> git commit
,就相當于把兩次修改合并后一塊提交了。
6.撤銷修改
第一種情況
- 修改了readme.txt文件,還沒有git add 和git commit
- 但是在你提交之前發現這次修改有問題。既然錯誤發現得很及時,就可以很容易地糾正它。你可以手動把文件恢復到上一個版本的狀態。
-
git checkout -- readme.txt
也可以通過命令撤銷修改,這條命令的意思就是,把readme.txt文件在工作區的修改全部撤銷 - 無論是文件修改后值存在于工作區還沒有放到暫存區,還是已經添加到暫存區,總之這個命令就是讓這個文件回到最近一次git commit或git add時的狀態。
- 查看文件,內容果然復原了。git checkout -- file命令中的--
很重要,沒有--
,就變成了“切換到另一個分支”的命令,我們在后面的分支管理中會再次遇到git checkout命令。
第二種情況
- 修改了readme.txt文件,而且執行了
git add readme.txt
- 慶幸的是你在 git commit 之前發現了這個問題
-
git status
查看一下,修改只是添加到了暫存區,還沒有提交 -
git reset HEAD readme.txt
可以把暫存區的修改撤銷掉,重新放回工作區。git reset命令既可以回退版本,也可以把暫存區的修改回退到工作區。當我們用HEAD時,表示最新的版本。 -
git status
查看一下,現在暫存區是干凈的,工作區有修改 -
git checkout -- readme.txt
還記得第一種情況中如何丟棄工作區的修改吧
第三種情況
現在,假設你不但改錯了東西,還從暫存區提交到了版本庫,怎么辦呢?還記得版本回退一節嗎?可以回退到上一個版本。不過,這是有條件的,就是你還沒有把自己的本地版本庫推送到遠程。
還記得Git是分布式版本控制系統嗎?我們后面會講到遠程版本庫,一旦你把錯誤的修改(如果是影響很大的錯誤)提交推送到遠程版本庫,你就真的慘了……
區別對待本地版本庫和遠程版本庫!
7.刪除文件
在Git中,刪除也是一個修改操作
- 添加一個新的文件 test.txt
git add test.txt
git commit test.txt -m "再次新增一個文件"
- 一般情況下,你通常會在文件管理器中把沒用的文件刪除,或者直接
rm test.txt
- `git status 這個時候,Git知道你刪除了文件,因此,工作區和版本庫就不一致了,git status命令會立刻告訴你哪些文件被刪除了
- 現在你有兩個選擇,一是確實從版本庫中刪除該文件,那就
git rm test.txt
,然后git commit
文件就從版本庫中刪除了 - 另一種情況是刪除錯了,因為版本庫里還有,所以可以輕松地將誤刪除的文件恢復到最新版本
git checkout -- test.txt
,git checkout其實使用版本庫中的版本替換工作區的版本,無論工作區是修改還是刪除,都可以“一鍵還原”
8.添加遠程庫
要想學習這部分的知識,請先參考下面的:a.配置連接遠程倉庫Github。
- 假如現在你已經配置好github,并且在github上添加了
learngit
倉庫。 -
git remote add origin git@github.com:michaelliao/learngit.git
這個命令是在本地的learngit倉庫下執行的,前面通過learngit倉庫為例我們已經講過在本地創建和操作git倉庫。這兩個地方的倉庫名不需要相同,因為會通過在本地的倉庫目錄下執行這條命令(命令中包含遠程庫的名字)已經將兩者建立了聯系 - 請千萬注意,把上面的michaelliao替換成你自己的GitHub賬戶名,否則,你在本地關聯的就是我的遠程庫,關聯沒有問題,但是你以后推送是推不上去的,因為你的SSH Key公鑰不在我的賬戶列表中。
-
git push -u origin master
把本地庫的所有內容推送到遠程庫上。把本地庫的內容推送到遠程,用git push命令,實際上是把當前分支master推送到遠程。由于遠程庫是空的,我們第一次推送master分支時,加上了-u參數,Git不但會把本地的master分支內容推送的遠程新的master分支,還會把本地的master分支和遠程的master分支關聯起來,在以后的推送或者拉取時就可以簡化命令。 - 然后去Github對應的遠程庫看看,都已經推送上去了。
- 此后,每次本地提交后,只要有必要,就可以使用命令
git push origin master
推送最新修改。
這樣你就可以在Github上托管你的項目代碼、vim的配置文件和插件、重要的文檔……
現在我的vim的配置文件和插件已經同步到Github上了:https://github.com/xumenger/m...
另外推薦我的關于vim配置的文章::http://segmentfault.com/a/119...
9.從遠程庫克隆
- 假設我的github上面有一個遠程庫,但是本地沒有,需要克隆到本地,遠程庫的名字叫'gitskills'
-
git clone git@github.com:michaelliao/gitskills.git
克隆一個本地庫 -
cd gitskills
進入克隆下來的本地庫,默認的名字是和github上的一樣的 -
ls -al
可以看到本地的克隆庫里面是和遠程庫里面的一樣的 - 如果有多個人協作開發,那么每個人各自從遠程克隆一份就可以了。
你也許還注意到,GitHub給出的地址不止一個,還可以用https://github.com/michaellia...這樣的地址。實際上,Git支持多種協議,默認的git://使用ssh,但也可以使用https等其他協議。
使用https除了速度慢以外,還有個最大的麻煩是每次推送都必須輸入口令,但是在某些只開放http端口的公司內部就無法使用ssh協議而只能用https。
10.分支管理
分支在實際中有什么用呢?假設你準備開發一個新功能,但是需要兩周才能完成,第一周你寫了50%的代碼,如果立刻提交,由于代碼還沒寫完,不完整的代碼庫會導致別人不能干活了。如果等代碼全部寫完再一次提交,又存在丟失每天進度的巨大風險。
現在有了分支,就不用怕了。你創建了一個屬于你自己的分支,別人看不到,還繼續在原來的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到開發完畢后,再一次性合并到原來的分支上,這樣,既安全,又不影響別人工作。
其他版本控制系統如SVN等都有分支管理,但是用過之后你會發現,這些版本控制系統創建和切換分支比蝸牛還慢,簡直讓人無法忍受,結果分支功能成了擺設,大家都不去用。
但Git的分支是與眾不同的,無論創建、切換和刪除分支,Git在1秒鐘之內就能完成!無論你的版本庫是1個文件還是1萬個文件。
11.創建和合并分支
首先教程中會詳細講解分支的原理(分支、指針、工作區……),一定要好好看!!看完之后你才能對你的創建分支和合并分支的操作不只是會用,更能在用的時候沒有任何疑惑!反正能學到更多的知識,何樂而不為!
另外推薦這樣的博客:使用git和github進行協同開發流程以及我的學習筆記使用git和github管理自己的項目---真實開發環境的策略。
在版本回退里,你已經知道,每次提交,Git都把它們串成一條時間線,這條時間線就是一個分支。截止到目前,我們練習的learngit,只有一條時間線,在Git里,這個分支叫主分支,即master
分支。HEAD嚴格來說不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是當前分支。
開始實戰:
-
git checkout -b dev
創建一個新的分支:dev,并且會切換到dev分支。所以這條命令有兩個作用。git checkout命令加上-b參數表示創建并切換,相當于以下兩條命令:git branch dev
和git checkout dev
- 補充:所有的git管理的項目剛開始時候默認有一條分支:master
-
git branch
查看當前所在的分支。git branch命令會列出所有分支,當前分支前面會標一個*號。 - 因為切換到dev分支,所以我們現在可以在dev分支上正常提交,比如對readme.txt做一個修改
git add readme.txt
git commit -m "提交到dev分支"
- git checkout master
現在,dev分支的工作完成,我們就可以切換回master分支 - 注意:切換回master分支后,再查看一個readme.txt文件,剛才添加的內容不見了!因為那個提交是在dev分支上,而master分支此刻的提交點并沒有變
-
git merge dev
這是在master分支上執行的命令,作用是:把dev分支上的工作成果合并到master分支上 - git merge命令用于合并指定分支到當前分支。合并后,再查看readme.txt的內容,就可以看到,和dev分支的最新提交是完全一樣的。注意到上面的Fast-forward信息,Git告訴我們,這次合并是“快進模式”,也就是直接把master指向dev的當前提交,所以合并速度非常快。當然,也不是每次合并都能Fast-forward,我們后面會將其他方式的合并。
-
git branch -d dev
合并完成之后,可以放心的刪除dev分支了 -
git branch
刪除后,查看branch,只剩下master了
12.解決沖突
教程中有詳細的圖文說明,很形象,很好!一定要參考!
人生不如意之事十之八九,合并分支往往也不是一帆風順的。
-
git checkout -b feature1
創建新的分支feature1,并且換到這個分支,進行新的實驗 - 在feature1分支下,假如將readme.txt的最后一行由"test branch" 改為"test feature1"
git add readme.txt
-
git commit -m "在feature1上修改readme.txt的最后一行"
在feature1分支上提交 -
git checkout master
切換到master分支。Git還會自動提示我們當前master分支比遠程的master分支要超前1個提交。 - 在master分支下,假如將readme.txt的最后一行由"test branch" 改為"test master"因為上面的是在feature1上進行的修改,所以切換回master之后,看到的文件并不是在feature1上修改后的文件
git add readme.txt
-
git commit -m "又在master上修改了readme.txt文件"
在master上也提交修改 - 現在,master分支和feature1分支各自都分別有新的提交
-
git merge feature1
在master分支上執行該命令,與feature1分支合并。這種情況下,Git無法執行“快速合并”,只能試圖把各自的修改合并起來,但這種合并就可能會有沖突,果然沖突了!Git告訴我們,readme.txt文件存在沖突,必須手動解決沖突后再提交 -
git status
git status也可以告訴我們沖突的文件 - 這時候使用vim等編輯器打開readme.txt文件可以看到已經在readme.txt文件中將沖突的信息已經添加到里面了,Git用
<<<<<<<
,=======
,>>>>>>>
標記出不同分支的內容 - 然后我們編輯readme.txt文件,處理沖突,將內容改成我們想要的樣子
git add readme.txt
-
git commit -m "解決沖突"
在master上提交 -
git log --graph --pretty=oneline --abbrev-commit
用帶參數的git log可以看到分支的合并情況。用git log --graph
命令可以看到分支合并圖。 -
git branch -d feature1
最后刪除feature分支,完成工作。
2015.09.09 今天就學到這里,實在太晚了,趕緊睡覺,明天還得工作!什么都沒有身體重要!明天繼續: 分支管理策略
a.配置連接遠程倉庫Github
首先看這篇文章了解git和SVN的區別,畢竟現在必須在工作中使用的就是SVN,所以還是弄清楚兩者的區別。
Git是分布式版本控制系統,同一個Git倉庫,可以分布到不同的機器上。怎么分布呢?最早,肯定只有一臺機器有一個原始版本庫,此后,別的機器可以“克隆”這個原始版本庫,而且每臺機器的版本庫其實都是一樣的,并沒有主次之分。
實際情況往往是這樣,找一臺電腦充當服務器的角色,每天24小時開機,其他每個人都從這個“服務器”倉庫克隆一份到自己的電腦上,并且各自把各自的提交推送到服務器倉庫里,也從服務器倉庫中拉取別人的提交。
完全可以自己搭建一臺運行Git的服務器,不過現階段,為了學Git先搭個服務器絕對是小題大作。好在這個世界上有個叫GitHub的神奇的網站,從名字就可以看出,這個網站就是提供Git倉庫托管服務的,所以,只要注冊一個GitHub賬號,就可以免費獲得Git遠程倉庫。
在繼續閱讀后續內容前,請自行注冊GitHub賬號。由于你的本地Git倉庫和GitHub倉庫之間的傳輸是通過SSH加密的,所以,需要一點設置:
- 創建SSH Key。在
用戶目錄
下,看看有沒有.ssh
目錄,如果有,再看看這個目錄下有沒有id_rsa
和id_rsa.pub
這兩個文件,如果已經有了,可直接跳到下一步。如果沒有,打開Shell(Windows下打開Git Bash),創建SSH Key,輸入命令ssh-keygen -t rsa -C "youremail@example.com"
,你需要把郵件地址換成你自己的郵件地址,然后一路回車,使用默認值即可,由于這個Key也不是用于軍事目的,所以也無需設置密碼。如果一切順利的話,可以在用戶主目錄里找到.ssh
目錄,里面有id_rsa
和id_rsa.pub
兩個文件,這兩個就是SSH Key的秘鑰對,id_rsa
是私鑰,不能泄露出去,id_rsa.pub
是公鑰,可以放心地告訴任何人。 - 登陸GitHub,打開“Account settings”,“SSH Keys”頁面.然后,點“Add SSH Key”,填上任意Title,在Key文本框里粘貼
id_rsa.pub
文件的內容:
- 點“Add Key”,你就應該看到已經添加的Key:
注意現在的Github的頁面的布局可能和圖片中顯示有細小的差別,不過相信你能找到對應的操作!
為什么GitHub需要SSH Key呢?因為GitHub需要識別出你推送的提交確實是你推送的,而不是別人冒充的,而Git支持SSH協議,所以,GitHub只要知道了你的公鑰,就可以確認只有你自己才能推送。
當然,GitHub允許你添加多個Key。假定你有若干電腦,你一會兒在公司提交,一會兒在家里提交,只要把每臺電腦的Key都添加到GitHub,就可以在每臺電腦上往GitHub推送了。
最后友情提示,在GitHub上免費托管的Git倉庫,任何人都可以看到喔(但只有你自己才能改)。所以,不要把敏感信息放進去。
如果你不想讓別人看到Git庫,有兩個辦法,一個是交點保護費,讓GitHub把公開的倉庫變成私有的,這樣別人就看不見了(不可讀更不可寫)。另一個辦法是自己動手,搭一個Git服務器,因為是你自己的Git服務器,所以別人也是看不見的。這個方法我們后面會講到的,相當簡單,公司內部開發必備。
現在的情景是,你已經在本地創建了一個Git倉庫后,又想在GitHub創建一個Git倉庫,并且讓這兩個倉庫進行遠程同步,這樣,GitHub上的倉庫既可以作為備份,又可以讓其他人通過該倉庫來協作,真是一舉多得。具體可以見教程。
首先,登陸GitHub,然后,在右上角找到“Create a new repo”按鈕,創建一個新的倉庫:
在Repository name填入
learngit
,其他保持默認設置,點擊“Create repository”按鈕,就成功地創建了一個新的Git倉庫:目前,在GitHub上的這個learngit倉庫還是空的,GitHub告訴我們,可以從這個倉庫克隆出新的倉庫,也可以把一個已有的本地倉庫與之關聯,然后,把本地倉庫的內容推送到GitHub倉庫。
本文轉載自:使用git和github管理自己的項目---基礎操作學習,進行了重新排版。二次轉載請注明原作出處。