走進GIT的世界(未完待續)

楔子

Git是什麼?
Git是目前世界上最先進的分佈式版本控制系統(沒有之一)。

Git有什麼特點?
簡單來說就是:高端大氣上檔次!

那什麼是版本控制系統?
VSS CVS GIT 都是,可自行搜索

集中式vs分佈式
https://www.liaoxuefeng.com/wiki/896043488029600/896202780297248

爲什麼要進行版本控制?這個問題回答的角度就太多了
代碼不能完全放在程序員本機的管理手段之一
備份的需求(回溯,找出歷史版本的需求)
通過版本的發佈高效的進行資料的投遞(避免歧義等)
版本控制是質量控制的重要組成部分
等等。


第一章 “故事”也特麼可以稱之爲“事故”

Linus在1991年創建了開源的Linux
Linux的壯大是靠全世界熱心的志願者參與
2002年以前,世界各地的志願者把源代碼文件通過diff的方式發給Linus,然後由Linus本人通過手工方式合併代碼
Linus堅定地反對CVS和SVN,這些集中式的版本控制系統不但速度慢,而且必須聯網才能使用。
有一些商用的版本控制系統,雖然比CVS、SVN好用,但那是付費的,和Linux的開源精神不符(有沒有覺得有點沙雕?

2002年,代碼庫之大讓Linus很難繼續通過手工方式管理了
社區的弟兄們也對這種方式表達了強烈不滿
於是Linus選擇了一個商業的版本控制系統BitKeeper
BitKeeper的東家BitMover公司出於人道主義精神授權Linux社區免費使用這個版本控制系統(人道主義?另一個沙雕來了

安定團結的大好局面在2005年就被打破了
原因是Linux社區牛人聚集,不免沾染了一些梁山好漢的江湖習氣。
開發Samba的Andrew試圖破解BitKeeper的協議(這麼幹的其實也不只他一個)
被BitMover公司發現了(沙雕年年有今年特別多)於是BitMover公司怒了,要收回Linux社區的免費使用權
Linus可以向BitMover公司道個歉,保證以後嚴格管教弟兄們,嗯,這是不可能的。實際情況是這樣的
Linus花了兩週時間自己用C寫了一個分佈式版本控制系統,這就是Git!
一個月之內,Linux系統的源碼已經由Git管理了!(靜觀一個沙雕牛逼的飛起來

2008年,GitHub網站上線了
歷史就是這麼偶然,如果不是當年BitMover公司威脅Linux社區,可能現在我們就沒有免費而超級好用的Git了。


第二章 天上地下宇宙無極唯我獨尊武學總綱

最有效的學習方法是講給別人聽(教授),再者是討論(現在天天給我初一的兒子灌輸這個費曼學習法)
而對我來說,最有效的學習方法有以下方面
從批判的角度來思考問題(多說幾個不,帶着問題進學習
環境如果已經存在,先接受結果,再考慮怎麼改進他(也就是常問幾個爲什麼
如果我自己要做一個GIT會是什麼樣子?我會怎麼來做呢?等。
先來看看已經存在的這個東西它是個啥吧,這裏先給出結論(時刻保持一顆對前人尊敬的心

因爲Git跟蹤並管理的是修改,而非文件。
因爲Git跟蹤並管理的是修改,而非文件。
因爲Git跟蹤並管理的是修改,而非文件。
(三遍,你懂的)

你會問,什麼是修改?
比如你新增了一行,這就是一個修改,
刪除了一行,也是一個修改,
更改了某些字符,也是一個修改,
刪了一些又加了一些,也是一個修改,
甚至創建一個新文件,也算一個修改。

如果不是管理修改,而是管理文件將會是什麼樣?
新建文本文檔
新建文本文檔(1)
新建文本文檔(2)
新建文本文檔-2020-03-03
新建文本文檔-2020-03-04-人事
同一個文檔會在你的電腦磁盤存成不同需求的不知道多少個副本
電腦硬盤(或者公司服務器)要足夠大,也許才能放的下
當人事問要一個文件的時候,你再手動的從這些文檔中找出來發給他,其實我們希望能通過一個系統進行交付的。

先上手試試,找已有的 git 試試看它怎麼管理修改的

手工建立一個文本文件 readme.txt,內容包含如下幾行

Git is a version control system.
Git is free software.

連續使用幾個git命令先看看它的效果($開頭的爲輸入的命令,仔細看,其他的是一些控制檯輸出,參考看)

$ git add readme.txt

$ git commit -m "wrote a readme file"
[master (root-commit) eaadf4e] wrote a readme file 1 file changed, 2 insertions(+)
 create mode 100644 readme.txt

//修改readme.txt 文件,內容如下(做實驗不用輸入這個cat命令,下同)
$ cat readme.txt
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes.

$ git add readme.txt

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
      modified:   readme.txt

//這次add完沒有立即commit,而是再次修改readme.txt 文件,內容如下
$ cat readme.txt 
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes of files.

//第二次修改後,進行commit
$ git commit -m "git tracks changes"
[master 519219b] git tracks changes 1 file changed, 1 insertion(+)

$ git status
On branch master
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:   readme.txt

no changes added to commit (use "git add" and/or "git commit -a")

咦,怎麼第二次的修改沒有被提交?
別激動,我們回顧一下操作過程:
第一次修改 -> git add -> 第二次修改 -> git commit

以上的控制檯看起來太複雜?簡單寫就是做如下這麼一個實驗。
編輯生成readme.txt
git add
git commit
修改readme.txt(第一次修改)
git add
修改readme.txt (這第二次修改並沒有被提交)
git commit


Git管理的是修改,當你用git add命令後,在工作區的第一次修改被放入暫存區,準備提交,
但是,在工作區的第二次修改並沒有放入暫存區
所以,git commit只負責把暫存區的修改提交了
也就是第一次的修改被提交了
第二次的修改不會被提交。

可以理解成,如果修改需要立即提交到版本庫,則 add 跟 commit應該成對的出現,這針對一個文件
對於多個文件,可以一次進行commit,例如

$ git add file1.txt
$ git add file2.txt file3.txt
$ git commit -m "add 3 files."

用這個例子來理解什麼叫做“管理修改”,以及理解git的這些命令(命名)
反過來說
git add 這個命令其實並不是把文件加入到git的倉庫
而是告訴git,
去對比一下倉庫跟開發者手頭手頭的代碼的差別
並且把這些差別記錄到暫存區去,也就是git管理的修改
如果你每次修改之後,不敲擊 git add 這個命令,其實git這個工具不會主動獲得變化的。
對於 git commit 這個命令的參數 -m" changes....." 應該指的是 memo 

當你要進行變化確認入庫時,最好還是帶上一個說明吧,對本次操作說明一下。


第三章 天降神器之屠龍在手

linux下的安裝

$ git
The program 'git' is currently not installed. You can install it by typing:
sudo apt-get install git

像上面的命令,有很多Linux會友好地告訴你Git沒有安裝,還會告訴你如何安裝Git。

Debian或Ubuntu Linux,sudo apt-get install git

老一點的Debian或Ubuntu Linux,要把命令改爲sudo apt-get install git-core
因爲以前有個軟件也叫GIT(GNU Interactive Tools),結果Git就只能叫git-core了。
由於Git名氣實在太大,後來就把GNU Interactive Tools改成gnuit,git-core正式改爲git。

如果是其他Linux版本,可以直接通過源碼安裝。
先從Git官網下載源碼,然後解壓
依次輸入:./config,make,sudo make install(需要有基本的編譯環境)

WINDOWS下的的安裝

git的下載(客戶端) 

官方頁面:https://git-scm.com/download/win
直接下載地址 https://github.com/git-for-windows/git/releases/download/v2.25.1.windows.1/Git-2.25.1-64-bit.exe

在開始菜單裏找到“Git”->“Git Bash”,蹦出一個類似命令行窗口的東西,就說明Git安裝成功!

基礎設置

$ git config --global user.name "Your Name"
$ git config --global user.email "[email protected]"

創建版本庫

// linux 下是這樣的

$ mkdir learngit
$ cd learngit
$ pwd
/Users/michael/learngit

$ git init
Initialized empty Git repository in /Users/michael/learngit/.git/

// windows 下是這樣

cd /d/work/raymotech                                                 // 鍵入命令
turui@turui-PC MINGW64 /d/work/raymotech                             // git bash 窗口顯示

$ git init                                                           // 鍵入命令
Initialized empty Git repository in D:/work/raymotech/.git/          // git bash 窗口顯示

turui@turui-PC MINGW64 /d/work/raymotech (master)                    // git bash 窗口顯示


瞬間Git就把倉庫建好了,而且告訴你是一個空的倉庫(empty Git repository)
細心的讀者可以發現當前目錄下多了一個.git的目錄
這個目錄是Git來跟蹤管理版本庫的
沒事千萬不要手動修改這個目錄裏面的文件
不然改亂了,就把Git倉庫給破壞了
如果你沒有看到.git目錄,那是因爲這個目錄默認是隱藏的
用 ls -ah命令就可以看見

講到這裏,必須重點說明一下,GIT最開始的使用一定爲單機(也就是個單機的遊戲)
如果單機的GIT都沒辦使用好的話,就更不要談聯網使用,Github的使用了
本地的版本庫有了,不管聯網不聯網,都可以嘗試測試、使用git的版本管理(控制)功能
等常用命令都熟悉了,行爲習慣也比較標準了,進階將重點完成聯網的使用(網絡遊戲)

Git能管理的文件類型

(原文中有些有歧義的說法我就沒有摘錄了)
版本控制系統可以告訴你每次的改動
比如在第5行加了一個單詞“Linux”,在第8行刪了一個單詞“Windows”。
而圖片、視頻這些二進制文件,雖然也能由版本控制系統管理,但沒法跟蹤文件的變化
只能把二進制文件每次改動串起來,也就是隻知道圖片從100KB改成了120KB
但到底改了啥,版本控制系統不知道,也沒法知道。
不幸的是,Microsoft的Word格式是二進制格式,
因此,版本控制系統是沒法跟蹤Word文件的改動的,
如果要真正使用版本控制系統,就要以純文本方式編寫文件。
我認爲,這裏應該描述爲
文本類型的文件,在版本控制系統的管理下,可以得到更多的管理細節
其他類型的文件,由於只能對比出二進制文件的大小等變化,所以管理細節比較粗糙

windows下文件(代碼)編輯的注意事項

因爲文本是有編碼的
比如中文有常用的GBK編碼
日文有Shift_JIS編碼
如果沒有歷史遺留問題,強烈建議使用標準的UTF-8編碼
所有語言使用同一種編碼,既沒有衝突,又被所有平臺所支持。
千萬不要使用Windows自帶的記事本編輯任何文本文件
Microsoft開發記事本的團隊使用了一個非常弱智的行爲來保存UTF-8編碼的文件
他們自作聰明地在每個文件開頭添加了0xefbbbf(十六進制)的字符
你會遇到很多不可思議的問題,比如,網頁第一行可能會顯示一個“?”
明明正確的程序一編譯就報語法錯誤,等等,都是由記事本的弱智行爲帶來的
建議你下載Notepad++代替記事本,不但功能強大,而且免費!
記得把Notepad++的默認編碼設置爲UTF-8 without BOM即可
set-utf8-notepad++

注:
這些都準備好之後,同學們,小朋友們就可以在本機愉快的玩耍了
下一章就讓我們一起來熟悉git命令吧
通過命令的使用看能解決哪些問題
通過命令的使用看能達到什麼樣的效果


第四章 無上祕籍之九陰九陽

官方文檔

 https://git-scm.com/docs

幫助

$ git --help
usage: git [--version] [--help] [-C <path>] [-c <name>=<value>]
           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
           [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]
           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
           <command> [<args>]

These are common Git commands used in various situations:

start a working area (see also: git help tutorial)
   clone             Clone a repository into a new directory
   init              Create an empty Git repository or reinitialize an existing one

work on the current change (see also: git help everyday)
   add               Add file contents to the index
   mv                Move or rename a file, a directory, or a symlink
   restore           Restore working tree files
   rm                Remove files from the working tree and from the index
   sparse-checkout   Initialize and modify the sparse-checkout

examine the history and state (see also: git help revisions)
   bisect            Use binary search to find the commit that introduced a bug
   diff              Show changes between commits, commit and working tree, etc
   grep              Print lines matching a pattern
   log               Show commit logs
   show              Show various types of objects
   status            Show the working tree status

grow, mark and tweak your common history
   branch            List, create, or delete branches
   commit            Record changes to the repository
   merge             Join two or more development histories together
   rebase            Reapply commits on top of another base tip
   reset             Reset current HEAD to the specified state
   switch            Switch branches
   tag               Create, list, delete or verify a tag object signed with GPG

collaborate (see also: git help workflows)
   fetch             Download objects and refs from another repository
   pull              Fetch from and integrate with another repository or a local branch
   push              Update remote refs along with associated objects

'git help -a' and 'git help -g' list available subcommands and some
concept guides. See 'git help <command>' or 'git help <concept>'
to read about a specific subcommand or concept.
See 'git help git' for an overview of the system.

設置全局信息

// 設置全局信息
$ git config --global user.name "Your Name"
$ git config --global user.email "[email protected]"

創建版本倉庫

// 創建版本倉庫,一般是空的時候才這樣用
$ git init

查看倉庫狀態

// 查看倉庫當前的狀態
$ git status

提交修改

// 告訴git去看下某個文件的變化
// 並將變化歸併(執行)到某個倉庫中
// 默認是歸併到master倉庫(repository)中
// 兩個一般成對使用
// 多個文件可以同時執行一個commit
$ git add readme.txt
$ git commit -m "wrote a readme file"

對比修改

// 上一次是如何修改的,顯示的格式正是Unix通用的diff格式
$ git diff readme.txt 

關於日誌

// 顯示從最近到最遠的提交日誌
// 可以看到3次提交
// 如果嫌輸出信息太多,看得眼花繚亂的,可以試試加上--pretty=oneline參數:
// 1094adb7b9b3807259d8cb349e7df1d4d6477073 這個叫commit id
$ git log
commit 1094adb7b9b3807259d8cb349e7df1d4d6477073 (HEAD -> master)
Author: Michael Liao <[email protected]>
Date:   Fri May 18 21:06:15 2018 +0800

    append GPL

$ git log --pretty=oneline
1094adb7b9b3807259d8cb349e7df1d4d6477073 (HEAD -> master) append GPL

關於版本回退

// 回退版本
// 上一個版本就是HEAD^
// 上上一個版本就是HEAD^^
// 當然往上100個版本寫100個^比較容易數不過來
// 所以寫成HEAD~100。
$ git reset --hard HEAD^
HEAD is now at e475afc add distributed
// 回退到任意版本
// 版本號沒必要寫全,前幾位就可以了
// Git會自動去找。當然也不能只寫前一兩位
// 因爲Git可能會找到多個版本號,就無法確定是哪一個了。
$ git reset --hard 1094a
HEAD is now at 83b0afe append GPL

HEAD指向的版本就是當前版本
Git的版本回退速度非常快,因爲Git在內部有個指向當前版本的HEAD指針
當你回退版本的時候,Git僅僅是把HEAD從指向append GPL

查看操作歷史

// 查看操作歷史
$ git reflog
e475afc HEAD@{1}: reset: moving to HEAD^
1094adb (HEAD -> master) HEAD@{2}: commit: append GPL
e475afc HEAD@{3}: commit: add distributed
eaadf4e HEAD@{4}: commit (initial): wrote a readme file

Git允許我們在版本的歷史之間穿梭
使用命令git reset --hard commit_id
穿梭前,用git log可以查看提交歷史,以便確定要回退到哪個版本。
要重返未來,用git reflog查看命令歷史,以便確定要回到未來的哪個版本。

關於 --hard 參數,這個講起來有點複雜,可以參考這裏(回頭專門補充一下)
https://www.cnblogs.com/keystone/p/10700617.html
reset這個操作還是要慎用!!!

文件找回

// git checkout -- file可以丟棄工作區的修改
// readme.txt自修改後,未放到暫存區,回到版本庫的狀態;
// readme.txt自修改後,已放到暫存區,回到暫存區的狀態;
// git checkout -- file命令中--很重要,沒有--,就變成了“切換到另一個分支”的命令
$ git checkout -- readme.txt

// git checkout -- file 會和 git reset HEAD file 組合使用
// 先回退文件在暫存庫的版本,再進行文件恢復
$ git reset HEAD readme.txt
$ git checkout -- readme.txt

文件刪除

// 刪除一個文件
// rm 刪除本地 git rm 提交刪除命令 git commit 成對使用
$ rm test.txt
$ git rm test.txt
rm 'test.txt'

$ git commit -m "remove test.txt"
[master d46f35e] remove test.txt 1 file changed, 1 deletion(-)
 delete mode 100644 test.txt

// 本地文件如果刪沒了,可以用 git check out 命令重新取回來
$ git checkout -- test.txt

遠程倉庫

// 本地倉庫跟遠程倉庫關聯、解除關聯相關操作
// 習慣上給遠程倉庫起名爲 origin 

// 列出已經存在的遠程分支
$ git remote 

// 列出詳細信息,在每一個名字後面列出其遠程url
// 此時, -v 選項顯示對應的克隆地址。
$ git remote -v | --verbose

// 添加一個遠程倉庫 
// git remote add <遠程倉庫名> <遠程倉庫url>
$ git remote add origin [email protected]:xxxxxx/xxxxxx.git

// 刪除一個遠程倉庫跟本地的關聯
// git remote remove repositiry_name

// 將本地的master倉庫push到遠程origin這個倉庫
$ git push -u origin master

數據推送(上傳)到遠程

// git push的一般形式爲 git push <遠程主機名> <本地分支名>  <遠程分支名>
$ git push origin master:refs/for/master

// 不帶任何參數的git push,默認只推送當前分支,這叫做simple方式
// 還有一種matching方式,會推送所有有對應的遠程分支的本地分支
// Git 2.0之前默認使用matching,現在改爲simple方式
// 如果想更改設置,可以使用git config命令。
// git config --global push.default matching 
// OR git config --global push.default simple
// 可以使用git config -l 查看配置


// 注意看下面的變形使用

// 如果遠程分支被省略
// 則表示將本地分支推送到與之存在追蹤關係的遠程分支(通常兩者同名)
// 如果該遠程分支不存在,則會被新建
$ git push origin master

// 如果省略本地分支名
// 則表示刪除指定的遠程分支
// 因爲這等同於推送一個空的本地分支到遠程分支
// 等同於 git push origin --delete master
$ git push origin :refs/for/master 

// 如果當前分支與遠程分支存在追蹤關係
// 則本地分支和遠程分支都可以省略
// 將當前分支推送到origin主機的對應分支
$ git push origin

// 如果當前分支只有一個遠程分支,那麼主機名都可以省略
// 形如 git push
// 可以使用git branch -r 查看遠程的分支名
$ git push

// 如果當前分支與多個主機存在追蹤關係
// 則可以使用 -u 參數指定一個默認主機
// 這樣後面就可以不加任何參數使用git push
$ git push -u origin master
$ git push


// 不管是否存在對應的遠程分支,將本地的所有分支都推送到遠程主機
$ git push --all origin 


// git push的時候需要本地先git pull更新到跟服務器版本一致
// 如果本地版本庫比遠程服務器上的低,那麼一般會提示你git pull更新
// 如果一定要提交,那麼可以使用這個命令。
$ git push --force origin 

// git push 的時候不會推送分支,如果一定要推送標籤的話那麼可以使用這個命令
$ git push origin --tags

克隆(遠程)數據到本地

// 關於git clone

// 在使用git來進行版本控制時,爲了得一個項目的拷貝(copy)
// 我們需要知道這個項目倉庫的地址(Git URL)
// Git能在許多協議下使用,所以Git URL可能以ssh://, http(s)://, git://
// 或是隻是以一個用戶名(git 會認爲這是一個ssh 地址)爲前輟. 

// 有些倉庫可以通過不只一種協議來訪問
// 例如,Git本身的源代碼你既可以用 git:// 協議來訪問:
$ git clone git://git.kernel.org/pub/scm/git/git.git

// 也可以通過http 協議來訪問:
$ git clone http://www.kernel.org/pub/scm/git/git.git

// git://協議較爲快速和有效
// 但是有時必須使用http協議,比如你公司的防火牆阻止了你的非http訪問請求.
// 如果你執行了上面兩行命令中的任意一個,你會看到一個新目錄: 'git'
// 它包含有所的Git源代碼和歷史記錄.

// 在默認情況下,Git會把"Git URL"裏最後一級目錄名的'.git'的後輟去掉
// 做爲新克隆(clone)項目的目錄名: 
// 例如. git clone http://git.kernel.org/linux/kernel/git/torvalds/linux-2.6.git
// 會建立一個目錄叫'linux-2.6'

// 另外,如果訪問一個Git URL需要用法名和密碼
// 可以在Git URL前加上用戶名,並在它們之間加上@符合以表示分割,
// 然後執行git clone命令,git會提示你輸入密碼。
$ git clone robin.hu@http://www.kernel.org/pub/scm/git/git.git
// 這樣將以作爲robin.hu用戶名訪問http://www.kernel.org/pub/scm/git/git.git
// 然後按回車鍵執行git clone命令,git會提示你輸入密碼。

// 另外,我們可以通過-b <name>來指定要克隆的分支名,比如
$ git clone -b master2 ../server .
// 表示克隆名爲master2的這個分支,如果省略-b <name>表示克隆master分支。

// 只克隆一個分支 攜帶這個參數 --single-branch
$ git clone -b mvp-dev-more --single-branch [email protected]:tancolo/MOOC.git

// 只想clone 某個git倉庫最近xx次提交的代碼
// --depth=commit_num 或者 --depth commit_num
git clone --depth=10 https://github.com/tancolo/MOOC.git

關於分支

每次提交Git都把它們串成一條時間線,這條時間線就是一個分支。(上一幅圖輔助理解下)
只有一條時間線,在Git裏,這個分支叫主分支,即master分支
每次提交,master分支都會向前移動一步,這樣,隨着你不斷提交,master分支的線也越來越長。
HEAD指向當前工作的分支(只有一個分支的時候 ,它當然指向master了)

git-br-initial
創建新的分支HEAD會指向新的分支(如圖)

git-br-create

新的分支再次做提交(commit)的時候,
HEAD會持續指向新的分支,也就是說HEAD這時候始終會指向當前工作的分支(如下圖)

git-br-dev-fd

當在dev分支進行合併操作時,實際上是在告訴git,把master(默認)分支弄的跟我一樣來
並且HEAD指向當前工作點(因爲已經合併了master跟dev是一個點)
 

git-br-ff-merge

如圖所示命令如下

// 首先,我們創建dev分支,然後切換到dev分支:
$ git checkout -b dev
Switched to a new branch 'dev'

// git checkout命令加上-b參數表示創建並切換,相當於以下兩條命令:
$ git branch dev
$ git checkout dev
Switched to branch 'dev'

// 然後,用git branch命令查看當前分支:
// git branch命令會列出所有分支,當前分支前面會標一個*號。
$ git branch
* dev
  master

// 然後,我們就可以在dev分支上正常提交
// 修改一下readme.txt,隨便添加一些內容,然後提交:
$ git add readme.txt 
$ git commit -m "branch test"
[dev b17d20e] branch test 1 file changed, 1 insertion(+)


// 現在,dev分支的工作完成,我們就可以切換回master分支:
$ git checkout master
Switched to branch 'master'

做完上述命令,git版本庫的情況是這樣的

git-br-on-master

所以這時候,你查看readme.txt文件,發現剛纔添加的內容不見了!

// 現在,我們把dev分支的工作成果合併到master分支上
$ git merge dev
Updating d46f35e..b17d20e
Fast-forward
 readme.txt | 1 + 1 file changed, 1 insertion(+)

合併完成後,GIT倉庫的狀態變爲圖4的情況
再查看readme.txt的內容,就可以看到,和dev分支的最新提交是完全一樣的。

注意到上面的Fast-forward信息,Git告訴我們,這次合併是“快進模式”
也就是直接把master指向dev的當前提交,所以合併速度非常快。
當然,也不是每次合併都能Fast-forward,我們後面會講其他方式的合併。
合併完成後,就可以放心地刪除dev分支了:

$ git branch -d dev
Deleted branch dev (was b17d20e).

刪除後,查看branch,就只剩下master分支了:

$ git branch
* master

我們注意到切換分支使用git checkout <branch>,和前面面講過的文件取回 git checkout -- <file> 同一個命令,有兩種作用,確實有點令人迷惑。
切換分支這個動作,用switch更科學。因此,最新版本的Git提供了新的git switch命令來切換分支

// 創建並切換到新的dev分支,可以使用:
$ git switch -c dev

// 直接切換到已有的master分支,可以使用:
$ git switch master

// 刪除分支:
$ git branch -d <name>

Git鼓勵大量使用分支

分支合併中的衝突,我們構造一種場景

git-br-feature1
什麼?上面這個場景不知道怎麼做?其實很容,命令如下

$ git switch -c feature1
Switched to a new branch 'feature1'

// 手工修改readme.txt

$ git add readme.txt
$ git commit -m "AND simple"
[feature1 14096d0] AND simple 1 file changed, 1 insertion(+), 1 deletion(-)

$ git switch master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 1 commit.  (use "git push" to publish your local commits)

// 手工修改readme.txt
$ git add readme.txt 
$ git commit -m "& simple"
[master 5dc6824] & simple 1 file changed, 1 insertion(+), 1 deletion(-)

從上面的圖形大家可以看出來,master分支和feature1分支各自都分別有新的提交
很明顯,這時候如果要做合併的話,衝突即將產生了
這種情況下,Git無法執行“快速合併”,只能試圖把各自的修改合併起來,
但這種合併就可能會有衝突,我們試試看

$ git merge feature1
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.

果然衝突了!Git告訴我們,readme.txt文件存在衝突,必須手動解決衝突後再提交。
手工(人爲)解決掉這些衝突後,再進行合併吧。
使用merge命令的時候,推薦加上參數 --no-ff(也就是默認什麼參數都不帶的Fast-forward模式並不推薦的,所以別偷懶哦

創建並切換dev分支
修改readme.txt,並add,commit
切回master
合併

git merge --no-ff -m “merge with no-ff” dev
 
--no-ff模式, 普通合併,有歷史,看得出做過合併
fast forward模式,快速合併,看不出做過合併
通常,合併分支時,
Git儘可能用 fast forward 模式,
但這種模式,刪除分支後,會丟掉分支信息。

實際開發中的分支管理策略

首先,master分支應該是非常穩定的,也就是僅用來發布新版本,平時不能在上面幹活;
幹活都在dev分支上,也就是說,dev分支是不穩定的,到某個時候,比如1.0版本發佈時,再把dev分支合併到master上,在master分支發佈1.0版本;
你和你的小夥伴們每個人都在dev分支上幹活,每個人都有自己的分支,時不時地往dev分支上合併就可以了。


第五章 抽絲剝繭之一窺究竟

前面反覆提到幾個名詞“工作區”、“暫存區”、“版本庫(又稱爲倉庫)”
看起來大概是這樣的

git-repo

工作區(Working Directory)就是你在電腦裏能看到的目錄
版本庫(Repository)工作區有一個隱藏目錄.git,這個不算工作區,而是Git的版本庫。
Git的版本庫裏存了很多東西,其中最重要的就是稱爲stage(或者叫index)的暫存區
還有Git爲我們自動創建的第一個分支master,以及指向master的一個指針叫HEAD

對於這3個區域常見的操作有

git add把文件從工作區>>>>暫存區

git commit把文件從暫存區>>>>倉庫

git diff查看工作區和暫存區差異

git diff --cached查看暫存區和倉庫差異

git diff HEAD 查看工作區和倉庫的差異

git checkout 放棄對工作區中某文件的修改
將工作區中該文件的狀態恢復到該文件上次提交到暫存區時的狀態。

add 會修改暫存區的內容
commit 會修改暫存區和倉庫的內容
checkout 會修改工作區的內容
reset 會修改工作區的內容


第六章 功力大成之渡劫飛昇

github

gitee


第七章 返璞歸真之自成一界

本地服務器搭建
nas的使用

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章