每天造輪子 - Git詳解

參考資料html

版本控制是什麼

概念

版本控制最主要的功能就是追蹤文件的變動。它將何時、什麼人更改了文件的什麼內容等信息忠實地了記錄下來。每一次文件的改變,文件的版本號都將增長。除了記錄版本變動外,版本控制的另外一個重要功能是並行開發。軟件開發每每是多人協同做業,版本控制能夠有效地解決版本的同步以及不一樣開發者之間的開發通訊問題,提升協同開發的效率。並行開發中最多見的不一樣版本軟件的錯誤(Bug)修正問題也能夠經過版本控制中分支與合併的方法有效地解決。vue

論必要性

  • 單人單功能開發 -- 至少你須要在開發在發現思路錯誤時快速退回到上一個正確的還原點
  • 單人多功能並行 + Bug fix -- 須要靈活的在多個功能點分支和Bug解決分支間切換
  • 多人多功能點 -- 須要多人間同步最新工做成果
  • 多人多功能點多版本多基線 -- 須要使用不一樣分支和Tag標識開發版本和里程碑,而且經過配置管理員將新的Feather和Bug Fix配置到不一樣的版本。

基礎功能

  • 檢入(Checkin)檢出(Checkout)控制
  • 分支合併
  • 歷史記錄

常見工具

  • CVS -- Dick Grune在1984年~1985年基於RCS開發的一個客戶一服務器架構的版本控制軟件,長久以來一直是免費版本控制軟件的主要選擇。
  • SVN -- SVN是一個比較好的開源版本控制工具
  • Git -- 今天的主題

Git的歷史

引用:廖雪峯的資料git

不少人都知道,Linus在1991年建立了開源的Linux,今後,Linux系統不斷髮展,已經成爲最大的服務器系統軟件了。 Linus雖然建立了Linux,但Linux的壯大是靠全世界熱心的志願者參與的,這麼多人在世界各地爲Linux編寫代碼,那Linux的代碼是如何管理的呢? 事實是,在2002年之前,世界各地的志願者把源代碼文件經過diff的方式發給Linus,而後由Linus本人經過手工方式合併代碼! 你也許會想,爲何Linus不把Linux代碼放到版本控制系統裏呢?不是有CVS、SVN這些免費的版本控制系統嗎?由於Linus堅決地反對CVS和SVN,這些集中式的版本控制系統不但速度慢,並且必須聯網才能使用。有一些商用的版本控制系統,雖然比CVS、SVN好用,但那是付費的,和Linux的開源精神不符。 不過,到了2002年,Linux系統已經發展了十年了,代碼庫之大讓Linus很難繼續經過手工方式管理了,社區的弟兄們也對這種方式表達了強烈不滿,因而Linus選擇了一個商業的版本控制系統BitKeeper,BitKeeper的東家BitMover公司出於人道主義精神,受權Linux社區無償使用這個版本控制系統。 安定團結的大好局面在2005年就被打破了,緣由是Linux社區牛人彙集,難免沾染了一些梁山好漢的江湖習氣。開發Samba的Andrew試圖【破】【解】BitKeeper的協議(這麼幹的其實也不僅他一個),被BitMover公司發現了(監控工做作得不錯!),因而BitMover公司怒了,要收回Linux社區的無償使用權。 Linus能夠向BitMover公司道個歉,保證之後嚴格管教弟兄們,嗯,這是不可能的。實際狀況是這樣的: Linus花了兩週時間本身用C寫了一個分佈式版本控制系統,這就是Git!一個月以內,Linux系統的源碼已經由Git管理了!牛是怎麼定義的呢?你們能夠體會一下。 Git迅速成爲最流行的分佈式版本控制系統,尤爲是2008年,GitHub網站上線了,它爲開源項目免費提供Git存儲,無數開源項目開始遷移至GitHub,包括jQuery,PHP,Ruby等等。 歷史就是這麼偶然,若是不是當年BitMover公司威脅Linux社區,可能如今咱們就沒有免費而超級好用的Git了。github

安裝

Linux

sudo apt-get install git
複製代碼

Mac

首先安裝homebrew,而後經過homebrew安裝Git,具體方法請參考homebrew的文檔:brew.sh/。緩存

brew install 
複製代碼

Windows

首先安裝Liunx子系統,而後參考Linux安裝指南bash

本地版本

建立本地倉庫

建立倉庫的過程其實就是將一個普通的文件夾升級爲一個具有版本控制能力的文件夾服務器

# 建立文件夾
mkdir hello-git
# 改變工做目錄到hello-git
cd hello-git
# 初始化Git至關將文件夾升級爲倉庫
git init
複製代碼

實際上git命令會在文件夾下建立一個.git文件夾全部後面神奇的版本控制功能都是經過這個文件夾裏面的這些神奇的文件實現的。 咱們能夠經過事先仰望一下後面用到了會給你們一一解析markdown

tree -a
複製代碼

將文件添加到版本庫

首先咱們建立一個文件架構

# 建立一個文件
echo 'Step01 Create File' >> README.md
複製代碼

而後咱們查看一下版本哭的狀態ssh

git status
複製代碼

咱們會發現Git會提示咱們這個文件屬於未跟蹤文件 若是在Vscode中

文件也會用綠色表示

其實Git的版本控制的要求也就是說即便處於版本庫文件夾內的文件你也要明確的聲明須要版本控制功能git纔會跟蹤他的版本變化。這樣的白名單作法是爲了防止多一些諸如編譯結果文件,日誌文件,開發工具本地配置等徹底沒有必要進行版本控制的文件進行了跟蹤佔用不必的系統資源。

將文件添加到版本庫

git add README.md
複製代碼

添加完成後我麼你發現這個時候文件狀態變爲要提交狀態。 這是由於相對於舊的版本記錄Git發現新添加了一個文件。咱們試用git status就能夠看到這樣的提示。

從暫存中恢復文件

一旦文件被提交到版本庫實際上Git就會將README文件的快照已經緩存了一份到暫存盤,若是有須要你還能夠將這個鏡像取出來。不信的話咱們能夠作一個小實驗。

# 刪除文件
rm -f README.md
# 從緩存區檢出文件
git checkout README.md
# 查看文件
cat README.md

複製代碼

另外若是你想一次添加多個和放棄跟蹤能夠參考下面的方法

添加多個文件跟蹤

# 添加本目錄下文件具有遞歸文件夾功能
git add .
複製代碼

取消跟蹤

# 取消添加
git rm --cached README.md
複製代碼

忽略文件.gitignore

若是你但願在使用 add .的時候忽略某一個文件能夠在目錄下建立一個 .gitignore文件

#.gitignore
# 忽略dist.js
dist.js
複製代碼

這個時候就可讓git文件放棄對此文件的關注。 固然若是你曾經將忽略的文件天交到git的跟蹤列表中的話,即便你你在ignore文件中聲明瞭git也不會主動放棄跟蹤

提交代碼commit

提交代碼是指已經完成了某一階段的代碼開發好比你完成了某一個代碼功能(features)或者修改了某一個代碼缺陷(fix),你就能夠建立一次代碼提交。

git commit -m 'add README.js'

複製代碼

提交的本質是講原有工做區的代碼提交到本地倉庫中,咱們看一下提交先後的對比。

保存臨時工做成果Stash

在你須要並行作好幾件事的時候,好比你正在開發一個功能程序開發到一半,有一個緊急的bug須要處理又或者你忽然對另一個新特性來了思路,可是你現有的代碼還在一箇中間狀態甚至編譯都有問題。你須要可定須要一個功能保存如今的工做現場,而後去幹另一件事。這個時候stash功能就能夠幫助你解決。

# 創建一個臨時的工做成果
echo 'TEMP xxxx' >> README.md

# 保存工做現場到棧
git stash

# 從棧中彈出工做現場
git stash pop


複製代碼

放棄修改

git restore .
複製代碼

回退到上一個提交

首先咱們修改一下文件,再作一次提交

echo 'STEP02 ADD FUN01' >> README.md
# 參數-a 是先添加到緩衝區再提交的意思
git commit -am 'README ADD STEP02'
複製代碼

這個時候咱們會有兩個提交記錄 咱們能夠用git log檢查一下

git log
git log –-oneline # 簡短日誌
git reflog # 操做記錄 包括回退記錄也會被顯示
複製代碼

# 只是版本回退 不更新工做區
git reset HEAD^

# 不但版本回退 也會更新工做區(文件目錄)的文件到上一個版本
git reset --hard HEAD^

複製代碼

工做區(Working Directory)、緩存區(Stage)、版本庫(Repository)小結

  • 工做區 --- 就是文件目錄由於你的開發工做就是對文件的修改因此叫作工做區
  • 緩存區 --- 沒有提交前也就是沒有完成完成工做結果代碼保存的地方
  • 版本庫 --- 每個工做結果的時間帶會被按照不一樣的提交記錄保存起來

分支管理

若是你每次只開發一個功能點或者修改一個Bug。不須要並行開發的可能你不須要分支。不過現實狀況是頗有可能你正在開發一個長達幾天的新特性時你又不的不去修改一些緊急的bug,又或是有個小夥伴急着讓你幫助他解決他所遇到的問題。這就有點像你須要不斷的從不一樣進度點開始玩遊戲。這個時候分支就能夠幫咱們解決這個問題。 git的分支管理在全部的版本控制工具中出類拔萃分廠推薦你們使用分支功能。

建立分支開發

默認狀況下咱們會處於master分支,在開始開發前咱們首先要作的就是切分一個新的分支。好比開發一個叫作FunA的功能點。

# 分支A
# 建立分支並切換分支到funA
git checkout -b 'funA'
# 完成功能
echo 'FunA XXXXXXX' >> README.md
# 提交功能
git commit -am 'funA add'
# 檢出master分支
git checkout master
# 合併將開發分支合併到主分支
git merge funA
# 能夠利用-d合併的同時刪除分支
git merge -d funA

複製代碼

分支的查看、刪除

# 查看
git branch 
# 查看 - a 包括遠程分支
git branch -a
# 刪除
git branch -D <分支名稱>

複製代碼

衝突解決

假設兩個分支都針對同一行代碼進行修改,就會形成衝突,須要人工肯定那一個分支獲得保留。 就比如兩我的一個主張走A路線,另外一個主張走B路線。最後須要再合併的時候決定到底走哪一個路線。

首先咱們先製造這樣一個衝突,假設咱們將開啓連個分支 分別將README文件的第一行 作不一樣而修改

  • step01 : Step01 Create File AAA
  • step01 : Step01 Create File BBB
# 建立分支並切換分支到funA
git checkout master
git checkout -b 'funA'
echo 'STEP01 AAA' > README.md
git commit -am 'step01 AAA'

# 建立分支並切換分支到
git checkout -b 'funB'
echo 'STEP01 BBB' > README.md
git commit -am 'step01 BBB'


# 能夠利用-d合併的同時刪除分支
git checkout master
git merge -d funA
git merge -d funB

複製代碼

因爲對同一行代碼進行了修改這個時候Git就須要人工區合併代碼 若是 想要撤銷merge狀態

git merge --abort
複製代碼

若是在VSCode編輯器中會更加清晰一些

下面要作的就是人工保留你須要的部分, 而後進行一次merge提交。其實取捨AAA仍是BBB自己就是一次變動因此其實就是一次的代碼commit。

git commit -am 'Merge branch funB'
複製代碼

最後咱們能夠經過log看一下此次合併過程

git log --graph --pretty=oneline --abbrev-commit
複製代碼

清洗提交歷史 -- squash方式合併

若是你的分支開發歷經各類磨難,裏面有不少細節的功能進展你不但願其餘人瞭解,又或者你在開發的過程當中肚子餓了,但願經過一次的commit來保留中間成果。可是最終提交的時候不但願你的這些中間細節被被人瞭解,能夠採用這樣的辦法

# 建立分支並切換分支到funA
git checkout master
git checkout -b 'funA'
echo 'STEP02 BBB' >> README.md
git commit -am 'FunA commit 01'
echo 'STEP03 BBB' >> README.md
git commit -am 'FunA commit 02'

# 切換master分支
# 使用squash方式提交 只合並不commit
git merge --squash funA
複製代碼

這個時候咱們能夠用git status查看一下發現合併代碼後並無提交。只是將全部的提交都整合到了一塊兒放在暫存區。

# 建立分支並切換分支到funA
git commit -am 'funA update'
複製代碼

這個時候咱們可使用commit方式進行提交留下光輝的而乾淨的一筆。

Rebase變基操做

去除版本合併痕跡 (待續)

其餘命令總結

# 刪除分支
git branch -D <branch_name>
複製代碼

標籤管理

標籤管理就是給本身的代碼打上版本標記。其實就是給本身的版本設置里程碑。

# 將最新提交打標籤
git tag v1.0

# 將指定commit打標籤
git tag v0.9 4ab025

# 查看打標籤
git tag 

# 查看與某標籤之間的差距
git show v0.9
複製代碼

遠程倉庫GitHub

如何獲取遠程倉庫

  • GitHub 世界上最大的開源社區
  • Gitee 國內的速度快
  • 本身搭建Gitlab

(後續會教你們如何一行配置搞定gitlab搭建)

git創建遠程倉庫

另外與遠程資源庫通信一般採用ssh協議,因此須要將你的ssh公鑰添加到github帳戶中

獲取公鑰的方法能夠參考 公鑰獲取方法

添加遠程分支

# 添加遠程分支
git remote add origin git@github.com:su37josephxia/hello-git.git

複製代碼

查看

git remote -v
複製代碼

推送 push

git push
複製代碼

拉去 fetch

git fetch
# 若是有多個遠程源時
git fetch <拉去源>
複製代碼

拉去 pull

至關與先fetch + merge

git pull
複製代碼

GitHub之Watch

表示關注、這個項目的全部動態包括PR ISSUE你的信息中心和郵箱都會收到。

GitHub之Star

表示點贊、表示對這個項目支持。 github.com/su37josephx… Star一下我這個項目。

歡迎你們來造輪子

GitHub之Fork

至關於複製了目前項目的文件,後續變化必須手動更新。 手動更新方法以下:

# 本地新加一個新的遠程庫upstream
git remote add upstream https://github.com/vuejs/vue-next

複製代碼
# 從遠程倉庫拉去代碼
git fetch upstream
# 切換分支
git chekout master
# 合併遠程分支
git merge upstream/master
複製代碼
相關文章
相關標籤/搜索