Git學習記錄(未完待續)

Git introduction

標籤(空格分隔): 版本控制 Gitjavascript

本文是我的對Git版本控制系統的學習,Git相關知識的學習。介紹Git的基本知識,經常使用操做等等。java


版本控制系統

VCS:Version Control System
版本控制系統是記錄文件的內容變化,以便在任什麼時候候能夠查看文件在特定版本修訂狀況的系統。它能夠對任何文件進行版本控制,無論是代碼文件、圖片文件、文檔文件等等。因此有了VCS以後咱們能夠將某個文件回退到以前的某一個狀態,甚至能夠將整個項目都回退到過去某個時間點的狀態。
固然經過VCS能夠比較文件具體的變化細節:git

+ var a = 5                                          - var a = 3
-        console.log(JSON.stringify(data))
-        console.log('isVcardUsing====', self.freeUse)
-        console.log(typeof self.freeUse)
+        // console.log(JSON.stringify(data))
+        // console.log('isVcardUsing====', self.freeUse)
+        // console.log(typeof self.freeUse)

這樣在出現一些bugs的時候咱們能夠去分析出最後是誰修改了哪一個地方,從而發現致使bugs的緣由,從而能夠快速修復問題。經過VCS的目的並非說要去追蹤是誰致使出現問題的人,而是幫助咱們快速的去解決問題。
不過目前不少公司有着一套版本發佈或持續集成系統,若是發佈上線以後發現有問題出現,能夠快速的回退到上一個指定沒有問題的版本,而後在經過分析致使bugs的緣由從新上線。
另外假設再開發過程當中不當心把項目中的文件改的改刪的刪,咱們也能夠輕鬆的恢復到原來的狀態。github

版本控制系統歷史分類:算法

  1. 本地版本控制系統:rcs
  2. 集中化版本控制系統CVCS:CVS,subversion……
  3. 分佈式版本控制系統DVCS:Git,Mercurial,Bazaar……

Git歷史

Linux內核開源項目有不少的參與者,可是絕大多數的Linux內核維護工做都花在提交補丁和保存歸檔的繁雜事務上面(1991-2002),到 2002 年,整個項目組開始啓用分佈式版本控制系統 BitKeeper 來管理和維護代碼。到了2005年,開發 BitKeeper 的商業公司同 Linux 內核開源社區的合做關係結束,他們收回了無償使用 BitKeeper 的權力。自此Git分佈式版本控制系統就誕生了。數據庫

Git當初設定的目標:api

  • 速度
  • 簡單的設計
  • 對非線性開發模式的強力支持(容許上千個並行開發的分支)
  • 徹底分佈式
  • 有能力高效管理相似 Linux 內核同樣的超大規模項目(速度和數據量)

Git基礎

理解Git的思想和基本工做原理,用起來就會知其因此然,遊刃有餘。安全

  • Git的原理是直接記錄快照,並不是差別比較:Git並不保存文件先後變化的差別數據,其實是把變化的文件作快照後,記錄在一個微型的文件系統中;
  • Git全部的操做都是本地執行;
  • 時刻保持數據的完整性:在保存到Git以前,全部的數據都會進行內容的校驗和(checksum)計算,並將此結果做爲數據的惟一標識和索引。
  • Git使用SHA-1算法計算數據的校驗和,此SHA-1 哈希值做爲指紋字符串,該字串由 40 個十六進制字符(0-9 及 a-f)組成;
  • 多數操做僅添加數據:經常使用的 Git 操做大多僅僅是把數據添加到數據庫;
  • 文件的三種狀態
    1.已修改 modified 表示修改了某個文件,但尚未提交保存
    2.已暫存 staged 表示把已修改的文件放在下次提交時要保存的清單中
    3.已提交 commited 表示該文件已經被安全地保存在本地數據庫中了

Git管理項目時,文件流的三個工做區域:Git工做目錄,暫存區域,本地倉庫(Git目錄.git)。服務器

clipboard.png


Git初始設置

  • git config --system --list (/etc/gitconfig)
  • git config --global --list (~/.gitconfig)
  • git config (--local) --list (當前項目的 git 目錄中的配置文件(也就是工做目錄中的 .git/config 文件))
  • git config --global user.name 'username'
  • git config --global user.email 'useremail'

若是用了 --global 選項,那麼更改的配置文件就是位於你係統用戶主目錄下的那個(~/.gitconfig),之後你全部的項目都會默認使用這裏配置的用戶信息。若是要在某個特定的項目中使用其餘名字或者電郵,只要去掉 --global 選項從新配置便可,新的設定保存在當前項目的 .git/config 文件裏。網絡

初始Git respository

有兩種取得 Git 項目倉庫的方法:
第一種是在現存的目錄下,經過導入全部文件來建立新的 Git 倉庫;
第二種是從已有的 Git 倉庫克隆出一個新的鏡像倉庫來;

第一種:

  • git init 當前目錄建立git倉庫
  • git init name 建立目錄爲name的git倉庫

第二種

  • git clone https://github.com/donnyqi/Html.git 拷貝遠程git倉庫,目錄爲Html
  • git clone https://github.com/donnyqi/Html.git HtmlTest 拷貝遠程git倉庫,目錄爲自定義的HtmlTest

記錄每次更新到倉庫

文件的狀態變化週期:
工做目錄下的全部文件都不外乎兩種狀態:已跟蹤 、 未跟蹤
已跟蹤的文件是指原本就被歸入版本控制管理的文件,在上次快照中有它們的記錄,工做一段時間後,它們的狀態多是未更新,已修改或者已放入暫存區。而全部其餘文件都屬於未跟蹤文件。它們既沒有上次更新時的快照,也不在當前的暫存區域。初次克隆某個倉庫時,工做目錄中的全部文件都屬於已跟蹤文件,且狀態爲未修改。

文件狀態變化週期:
圖片描述

狀態的提示語:

  • untracked Untracked files,未跟蹤文件
  • unmodified 未作任何修改
  • modified Changes not staged for commit,已修改文件
  • staged Changes to be committed,已暫存文件

基本的 Git 工做流程以下:

1.在工做目錄新加了文件--->Untracked files(工做目錄新加文件)
2.在工做目錄中修改某些文件--->modified:Changes not staged for commit(工做目錄修改了文件)
3.對新加的文件、修改後的文件進行快照(git add操做),而後保存到暫存區域--->staged:Changes to be committed(修改的文件保存到暫存區域)
4.提交更新(git commit操做),將保存在暫存區域的文件快照永久轉儲到Git目錄中--->commited(暫存區域的文件提交到本地倉庫)
bogon:static vivo$ git status
On branch branch_point_20180426_v3_2_1
Your branch is up-to-date with 'origin/branch_point_20180426_v3_2_1'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   src/api/test.js

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   src/api/index.js
        modified:   src/router/index.js

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        src/views/Test/

Git 基礎命令操做

  • git status 檢查當前文件狀態
  • git log 查看提交歷史,git log具備不少格式化參數,建議使用圖形化工具gitk,至關於git log命令的可視化版本
  • git add filename || 目錄 跟蹤新文件,已跟蹤文件&未跟蹤文件放到暫存區(譯註:其實 git add 的潛臺詞就是把目標文件快照放入暫存區域,也就是 add file into staged area,同時不曾跟蹤過的文件標記爲須要跟蹤。這樣就好理解後續 add 操做的實際意義了。)
  • git add . 跟蹤全部文件
  • git diff (--cached || --staged) 查看已暫存文件或未暫存文件與暫存區域快照之間的更新
  • git diff 查看工做目錄中當前未暫存的文件與暫存區域快照直接的差別,也就是修改以後尚未暫存起來的變化內容。若是未暫存的文件所有都add到暫存區域,git diff是沒有變化的;若是新加的文件(Untracked files),git diff也是沒有變化的
  • git diff --cached || --staged 當前工做目錄中已暫存文件與上次提交時的快照之間的差別 或者經過開發工具比較
  • git commit 進入Vim輸入本次提交的說明(默認的提交消息包含最後一次運行 git status 的輸出)->i->input commit message->esc-> : ->wq->enter
  • git commit -v 進入Vim輸入本次提交的說明(將修改差別的每一行都包含到註釋中來)
  • git commit -m "commit message" 直接提交說明
  • git commit -a -m "commit message" Git會自動把全部已經跟蹤過的文件暫存起來一併提交直接加到staged區域,從而跳過 git add 步驟,可是不能添加untracked文件(-a : 此操做跳過了git add 操做)
  • git commit -a 進入Vim輸入本次提交的說明,把已經跟蹤過的文件暫存到暫存區域,可是不能添加untracked文件(-a : 此操做跳過了git add 操做)
  • git commit --amend 進入Vim修改最後一次提交的提交信息。此操做提交的文件快照和以前是同樣的,只是從新編輯提交說明並覆蓋。若是剛纔提交時忘了暫存某些修改,能夠先補上暫存操做,而後再運行 --amend 提交:

    git commit -m "message"
      git add 'filename'
      git commit --amend
      上面三條命令最終只會產生一個提交,以第二個提交命令的提交信息爲準
  • git mv old_filename new_filename 重命名文件
  • git mv path/old_filename path/new_filename 移動文件而且重命名文件
  • git reset (HEAD) filename 取消已經暫存的文件(放棄工做目錄中當前暫存的文件到未暫存或未追蹤)
  • git checkout filename 取消對文件的修改(放棄工做目錄中當前修改的文件),注:可是取消對文件的修改操做執行時候全部對文件的修改就都沒有了,是有風險的,全部在執行此操做前確保真的再也不須要保留剛纔的修改

注:若是在新跟蹤了某個untracked文件或者在跟蹤了某個已修改後的文件,添加到staged區域(Changes to be committed)以後,再次對該跟蹤的文件進行了修改,這個時候若是如今提交,那麼提交的是以前add的版本,而非當前工做目錄中的版本。因此,運行了 git add 以後又做了修訂的文件,須要從新運行 git add 把最新版本從新暫存起來

Git 遠程倉庫的使用

  • git remote 每一個遠程庫的簡短名字
  • git remote -v 顯示對於的克隆地址
  • git remote add shortname url 添加遠程倉庫:git remote add pb git://github.com/paulboone/ticgit.git
  • git fetch remote-name 從遠程倉庫抓取數據
  • git push remote-name branch-name 本地倉庫中的數據推送到遠程倉庫
  • git remote show remote-name 查看遠程倉庫信息
  • git remote rename old-remote-name new-remote-name 修改某個遠程倉庫在本地的簡稱
  • git remote rm remote-name 移除對應的遠端倉庫

Git標籤 tag

Git 使用的標籤有兩種類型:輕量級的(lightweight)和含附註的(annotated)。輕量級標籤就像是個不會變化的分支,實際上它就是個指向特定提交對象的引用。而含附註標籤,其實是存儲在倉庫中的一個獨立對象,它有自身的校驗和信息,包含着標籤的名字,電子郵件地址和日期,以及標籤說明,標籤自己也容許使用 GNU Privacy Guard (GPG) 來簽署或驗證。通常咱們都建議使用含附註型的標籤,以便保留相關信息;固然,若是隻是臨時性加註標籤,或者不須要旁註額外信息,用輕量級標籤也沒問題。

  • git tag 列出全部的標籤
  • git tag -l v1.7* 列出全部包含v1.7標籤
  • git tag tag-name 建立一個輕量級tag
  • git tag -a tag-name -m annotated 建立一個含附註的標籤(-m 選項則指定了對應的標籤說明,Git 會將此說明一同保存在標籤對象中。若是沒有給出該選項,Git 就會啓動文本編輯軟件供你輸入標籤說明。相似commit -m)
  • git tag -a tag-name commitid 後期加註標籤,在後期對早先的某次提交加註標籤
  • git show tag-name 查看相應標籤的版本信息,並連同顯示打標籤時的提交對象
  • git tag -d tag-name 刪除tag
  • git push origin tagname 推送tag到遠端服務器
  • git push origin --tags 推送全部本地全部tags到遠端服務器

Git 分支

Git 的分支可謂是難以置信的輕量級,它的新建操做幾乎能夠在瞬間完成,而且在不一樣分支間切換起來也差很少同樣快。和許多其餘版本控制系統不一樣,Git 鼓勵在工做流程中頻繁使用分支與合併,哪怕一天以內進行許屢次都沒有關係。理解分支的概念並熟練運用後,你纔會意識到爲何 Git 是一個如此強大而獨特的工具,並今後真正改變你的開發方式。
爲了理解 Git 分支的實現方式,咱們須要回顧一下 Git 是如何儲存數據的:Git 保存的不是文件差別或者變化量,而只是一系列文件快照。
**Git 中的分支,其實本質上僅僅是個指向 commit 對象的可變指針(分支其實就是從某個提交對象往回看的歷史)。**
Git 是如何知道你當前在哪一個分支上工做的呢?Git保存着一個名爲 HEAD 的特別指針,它是一個指向你正在工做中的本地分支的指針(注:將 HEAD 想象爲當前分支的別名。

這和大多數版本控制系統造成了鮮明對比,它們管理分支大多采起備份全部項目文件到特定目錄的方式,因此根據項目文件數量和大小不一樣,可能花費的時間也會有至關大的差異,快則幾秒,慢則數分鐘。而 Git 的實現與項目複雜度無關,它永遠能夠在幾毫秒的時間內完成分支的建立和切換。同時,由於每次提交時都記錄了祖先信息(譯註:即 parent 對象),未來要合併分支時,尋找恰當的合併基礎(譯註:即共同祖先)的工做其實已經天然而然地擺在那裏了,因此實現起來很是容易。Git 鼓勵開發者頻繁使用分支,正是由於有着這些特性做保障。

  • git branch branch-name 新建一個分支
  • git checkout branch-name 切換到輸入的分支上,HEAD就會指向checkout的分支
  • git checkout -b branch-name 新建一個分支而且切換到該分支上,至關於上面兩步的合併
  • git merge branch-name 將輸入的分支合併到當前分支
  • git branch 列出git倉庫本地的全部分支
  • git branch -a 列出git倉庫遠程與本地全部分支
  • git branch -v 查看各個分支最後一個提交對象的信息
  • git branch --merge 從分支清單中篩選出你已經與當前分支合併的分支
  • git branch --no-merge 從分支清單中篩選出你還沒有與當前分支合併的分支
  • git branch -d branch-name 刪除分支
  • git branch -D branch-name 強制刪除分支

遠程分支

遠程分支(remote branch)是對遠程倉庫中的分支的索引。它們是一些沒法移動的本地分支;只有在 Git 進行網絡交互時纔會更新。遠程分支就像是書籤,提醒着你上次鏈接遠程倉庫時上面各分支的位置。
咱們用 遠程倉庫名/分支名 這樣的形式表示遠程分支。

  • git fetch origin 同步遠程服務器上的數據到本地,origin爲遠程倉庫的簡短名字(默認爲origin)
  • git push 遠程倉庫名 分支名 推送分支
  • git push 遠程倉庫名 本地分支名:遠程分支名

    git push origin master
    git push origin master:master
    git push origin master:refs/heads/master
    git push origin refs/heads/master:refs/heads/master
    上面四條命令的效果是同樣的
    
    你也能夠把本地分支推送到某個命名不一樣的遠程分支:若想把遠程分支叫做 anotherbranch,能夠用:
    git push origin `branch-name`:`anotherbranch-name` 來推送數據
  • git push origin :遠程分支名 刪除遠程分支
  • git branch -r -d origin/v1.0 刪除遠程分支

跟蹤遠程分支

  • git checkout --track 遠程倉庫名/遠程分支名
  • git checkout 遠程分支名
  • git checkout -b 分支名 遠程倉庫名/遠程分支名

    git checkout --track origin/test
    git checkout test
    上面兩個命令效果相同
    要爲本地分支設定不一樣於遠程分支的名字:git checkout -b test-alias origin/test

分支的衍合

把一個分支中的修改整合到另外一個分支的辦法有兩種:merge(合併) 和 rebase(衍合)
最容易的整合分支的方法是 merge 命令,它會把兩個分支最新的快照(C3 和 C4)以及兩者最新的共同祖先(C2)進行三方合併,合併的結果是產生一個新的提交對象(C5)
rebase 命令:把在一個分支裏提交的改變移到另外一個分支裏重放一遍

  • git rebase master
  • git rebase --continue 處理完衝突繼續合併
  • git rebase --skip 跳過
  • git rebase --abort 取消合併

衍合的原理是回到兩個分支最近的共同祖先,根據當前分支(也就是要進行衍合的分支)後續的歷次提交對象(這裏只有一個 C3),生成一系列文件補丁,而後以基底分支(也就是主幹分支 master)最後一個提交對象(C4)爲新的出發點,逐個應用以前準備好的補丁文件,最後會生成一個新的合併提交對象(C3'),從而改寫 experiment 的提交歷史,使它成爲 master 分支的直接下游,以下圖所示:
圖片描述
其實衍合和普通的三方合併(merge),對應的快照內容如出一轍了。雖然最後整合獲得的結果沒有任何區別,但衍合能產生一個更爲整潔的提交歷史。若是視察一個衍合過的分支的歷史記錄,看起來會更清楚:彷彿全部修改都是在一根線上前後進行的,儘管實際上它們本來是同時並行發生的。
請注意,合併結果中最後一次提交所指向的快照,不管是經過衍合,仍是三方合併,都會獲得相同的快照內容,只不過提交歷史不一樣罷了。衍合是按照每行的修改次序重演一遍修改,而合併是把最終結果合在一塊兒。

相關文章
相關標籤/搜索