版本控制

Git

Git是一個分布式版本控制系統(Distributed Version Control System - DVCS)

版本控制系統(Version Control System - VCS)

核心:版本控制,主動提交,中央倉庫三個要素

中央式版本控制系統(Centralized VCS)

中央倉庫的作用:保存版本歷史,同步團隊代碼

分布式版本控制系統(Distributed VCS/DVCS)

分布式VCS除了中央倉庫之外,還有本地倉庫。
一.工作模型:
1.首先代碼提交到本地倉庫;
2.在服務器創建一個中央倉庫,把代碼從本地倉庫推送到服務器的中央倉庫;
3.其他同事把中央倉庫的內容克隆到本地,擁有了各自的本地倉庫;
4.在功能開發中,一個人會把它的每一步改動提交到本地倉庫,再從本地倉庫推送到中央倉庫;
5.另外兩個人就可以選擇把這些提交同步到自己的機器上,并把它們和自己的本地代碼合并。
二.優點:
大多數的操作可以在本地進行,所以速度更快,而且由于無需聯網;由于可以提交到本地,所以你可以分步提交代碼,把代碼提交做得更細,而不是一個提交包含很多代碼,難以 review 也難以回溯;
三.缺點:
由于每一個機器都有完整的本地倉庫,所以初次獲取項目(Git 術語:clone)的時候會比較耗時;本地占用的存儲比中央式 VCS 要高。

Git基本使用

下載地址:Git下載

  1. 在GitHub通過New Repository來新建遠程倉庫,在Create a new
    repository的時候,填寫Repository name,Add.gitignore:Android,最后點擊Create repository完成創建;創建完成后,點擊右邊Clone or download,把倉庫的clone地址復制到剪貼板;
  2. 從GitHub把中央倉庫clone到本地(使用命令:git clone)
    git clone 復制的地址
    注:.git 目錄就是你的本地倉庫(Local Repository),所有的版本信息都會存在這里,而.git所在的根目錄,稱為Git的工作目錄(Working Directory),它保存了你當前從倉庫中checkout的內容。
    在項目的目錄下輸入:git log 查看提交歷史
  3. 代碼提交(先用git add 文件名把文件添加到暫存區,再用git commit提交)
    在這個過程中,可以使用git status來隨時查看工作目錄的狀態
    image.png

    注:每個文件有"changed/unstaged"(已修改),"staged"(已修改并暫存),"commited"(已提交)三種狀態,以及一種特殊狀態"untracked"(未跟蹤)

用add指令來讓Git開始跟蹤:git add eZhouXingV5-Android
再次輸入git status

image.png

提交的方式是用commit指令:git commit
在初始狀態下,你是在命令模式,不能編輯這個文件,你需要按一下 "i"(小寫)來切換到插入模式,然后就可以輸入你的提交信息了;
在輸入完成后別按回車,而是要按 ESC 鍵返回到命令模式,然后連續輸入兩個大寫的 "Z"(用 Shift 鍵或 Capslock 鍵都可以),就保存并退出了;

  1. 提交一次或多次之后,把本地提交push到中央倉庫(git push)
    可以使用git push來把你的本地提交發布(即上傳到中央倉庫)

團隊工作的基本工作模型

模擬同事的本地倉庫:
git clone 地址 文件名
從遠程倉庫更新內容使用: git pull
流程:同事commit代碼到他的本地,并push到GitHub中央倉庫;你把GitHub的新提交通過pull指令來取到你的本地;

push沖突:由于 GitHub 的遠端倉庫上含有本地倉庫沒有的內容,所以這次 push 被拒絕了;
解決方式:先用 pull 把遠端倉庫上的新內容取回到本地和本地合并,然后再把合并后的本地倉庫向遠端倉庫推送;
多人合作的基本工作模型:

  1. 寫完所有的 commit 后,不用考慮中央倉庫是否有新的提交,直接 push 就好;
  2. 如果 push 失敗,就用 pull 把本地倉庫的提交和中央倉庫的提交進行合并,然后再 push 一次;

進階 1:HEAD、master 與 branch

HEAD

當前commit的引用,它指的就是當前工作目錄所對應的commit;它具有唯一性,每個倉庫中只有一個 HEAD。在每次提交時它都會自動向前移動到最新的 commit 。

branch分支

HEAD 除了直接指向 commit,也可以通過指向某個 branch 來間接指向 commit。當 HEAD 指向一個 branch 時,commit 發生時,HEAD 會帶著它所指向的 branch 一起移動。

master 默認branch

主branch/主分支

  1. 新建的倉庫中的第一個 commit 會被 master 自動指向;
  2. 在 git clone 時,會自動 checkout 出 master。
branch的創建,切換和刪除
  1. 創建branch:git branch 名稱
  2. 切換branch: git checkout 名稱
    可以用git checkout -b 名稱創建后自動切換,用指定的名稱創建 branch 后,再直接切換過去;
  3. 刪除branch: git branch -d 名稱
    HEAD 指向的 branch 不能刪除。如果要刪除 HEAD 指向的 branch,需要先用 checkout 把 HEAD 指向其他地方。

進階 2:push 的本質

  1. push 是把當前的分支上傳到遠程倉庫,并把這個 branch 的路徑上的所有 commits 也一并上傳;
  2. push 的時候,如果當前分支是一個本地創建的分支,需要指定遠程倉庫名和分支名,用git push origin branch_name 的格式,而不能只用 git push;或者可以通過 git config 修改 push.default 來改變 push 時的行為邏輯。
  3. push 的時候之后上傳當前分支,并不會上傳 HEAD;遠程倉庫的 HEAD 是永遠指向默認分支(即 master)的;

進階 3:merge:合并 commits

  1. merge含義:從兩個 commit「分叉」的位置起,把目標 commit 的內容應用到當前 commit(HEAD 所指向的 commit),并生成一個新的 commit;執行git merge branch1
  2. merge的使用場景:
    單獨開發的branch用完了以后,合并回原先的branch;
    git pull的內部自動操作

pull的內部操作:pull的實際操作其實是把遠端倉庫的內容用fetch取下來之后,用merge來合并;
merge在合并的時候,是有一定的自動合并能力的,如果一個分支改了A文件,另一個分支改了B文件,那么合并后就是既改A也改B;如果兩個分支都改了同一個文件,但一個改的是第 1 行,另一個改的是第 2 行,那么合并后就是第 1 行和第 2 行都改,也是自動完成。

  1. merge的三種特殊情況
    3.1 原因:當前分支和目標分支修改了同一部分內容,Git無法確定應該怎樣合并;
    應對方法:解決沖突后手動commit;


    image.png

    Git 添加了三行符號 <<< === >>>
    3.2 HEAD領先于目標commit: Git什么也不做,空操作;
    3.3 HEAD落后于目標commit:fast-forward;

進階 4:Feature Branching:最流行的工作流

簡介:

  1. 任何新的功能(feature)或 bug 修復全都新建一個 branch 來寫;
  2. branch 寫完后,合并到 master,然后刪掉這個 branch;
git checkout -b books;//創建一個新的branch叫做books
git push origin books;//把代碼push到中央倉庫
git pull;//同事從中央倉庫拉下代碼
git checkout books;//切換到分支books
// 合并到master
git checkout master;
git pull;//merge之前pull一下,讓master更新到和遠程倉庫同步
git merge books;//合并books分支
// 合并后的結果push到了中央倉庫,并刪掉了books這個branch
git push;
git branch -d books;
git push origin -d books// 用-d參數把遠程倉庫的branch也刪了

進階 5:關于 add

add把改動的內容放進暫存區

1. add后面加個點'.':全部暫存

git add .直接把工作目錄下的所有改動全部放進暫存區;

2. add添加的是文件改動,而不是文件名

進階 6:看看我都改了什么

git log可以查看歷史記錄

1. 查看歷史中的多個commit: log

查看詳細改動:git log -p;
查看大致改動: git log --stat

2. 查看具體某個commit: show

要看最新 commit ,直接輸入 git show;要看指定 commit ,輸入 git show commit的引用或SHA-1;
如果還要指定文件,在 git show 的最后加上文件名

3. 查看未提交的內容:diff

查看暫存區和上一條 commit 的區別:git diff --staged(或 --cached)
查看工作目錄和暫存區的區別:git diff 不加選項參數
查看工作目錄和上一條 commit 的區別:git diff HEAD

高級 1:不喜歡 merge 的分叉?用 rebase 吧

rebase——在新位置重新提交,重寫設置基礎點,改變commit序列的基礎點
使用方式:git rebase 目標基礎點

git checkout branch1
git rebase master
// 在rebase之后,記得切回master再merge一下,把master移動最新的commit:
git checkout master
git merge branch1

高級 2:剛剛提交的代碼,發現寫錯了怎么辦?

用 commit --amend 可以修復當前提交的錯誤: git commit --amend,commit --amend 并不是直接修改原 commit 的內容,而是生成一條新的 commit。

git add 笑聲.txt
git commit --amend

高級 3:寫錯的不是最新的提交,而是倒數第二個?

commit --amend 可以修復最新 commit 的錯誤,但如果是倒數第二個 commit 寫錯了,怎么辦?

rebase -i:交互式 rebase

開啟交互式 rebase 過程: git rebase -i HEAD^^
把當前 commit ( HEAD 所指向的 commit) rebase 到 HEAD 之前 2 個的 commit 上;
交互式 rebase 最常用的場景是修改寫錯的 commit

  1. 使用方式是 git rebase -i 目標commit;
  2. 在編輯界面中指定需要操作的 commits 以及操作類型;
  3. 操作完成之后用git rebase --continue 來繼續 rebase 過程。

高級 4:比錯還錯,想直接丟棄剛寫的提交?

reset --hard 丟棄最新的提交

git reset --hard HEAD^:HEAD^ 表示你要恢復到哪個 commit。因為你要撤銷最新的一個 commit,所以你需要恢復到它的父 commit ,也就是 HEAD^。那么在這行之后,你的最新一條就被撤銷了

高級 5:想丟棄的也不是最新的提交?

用交互式 rebase 撤銷提交

交互式 rebase 可以用來修改某些舊的 commits。其實除了修改提交,它還可以用于撤銷提交;
你想撤銷倒數第二條 commit,那么可以使用 rebase -i:git rebase -i HEAD^^

用 rebase --onto 撤銷提交

在 rebase 命令中直接剔除想撤銷的 commits

高級 6:代碼已經 push 上去了才發現寫錯?

1. 出錯的內容在你自己的 branch

如果你在本地對已有的commit做了修改,這時你再push就會失敗,因為中央倉庫包含本地沒有的commits,這時選擇強行push:
git push origin branch1 -f:忽略沖突,強制push

2. 出錯的內容已經合并到 master

增加一個新的提交,把之前的提交的內容抹掉;
不要強制 push,而要用 revert 把寫錯的 commit 撤銷;git revert HEAD^

高級 7:reset 的本質——不止可以撤銷提交

reset 的本質:移動 HEAD 以及它所指向的 branch

reset --hard HEAD^它把 HEAD 和它所指向的 branch 一起移動到了當前 commit 的父 commit 上,從而起到了「撤銷」的效果;
把 HEAD 和 branch 移動到其他的任何地方:git reset --hard branch2

reset --hard:重置工作目錄

重置位置的同時,清空工作目錄的所有改動;

reset --soft:保留工作目錄

r重置位置的同時,保留工作目錄和暫存區的內容,并把重置 HEAD 的位置所導致的新的文件差異放進暫存區;

reset 不加參數:保留工作目錄,并清空暫存區

--mixed(默認):重置位置的同時,保留工作目錄的內容,并清空暫存區。

高級 8:checkout 的本質

git checkout branch名: checkout 的本質是簽出指定的 commit,所以你不止可以切換 branch,也可以直接指定 commit 作為參數,來把 HEAD 移動到指定的 commit。

checkout 和 reset 的不同

reset 在移動 HEAD 時會帶著它所指向的 branch 一起移動,而 checkout 不會。當你用 checkout 指向其他地方的時候,HEAD 和 它所指向的 branch 就自動脫離了。

高級 9:緊急情況:「立即給我打個包,現在馬上!」

stash:臨時存放工作目錄的改動

在 Git 中,stash 指令可以幫你把工作目錄的內容全部放在你本地的一個獨立的地方,它不會被提交,也不會被刪除,你把東西放起來之后就可以去做你的臨時工作了,做完以后再來取走,就可以繼續之前手頭的事了。git stash
打完包切回你的分支: git stash pop

高級 10:branch 刪過了才想起來有用?

branch 用完就刪是好習慣

reflog :引用的 log

查看一下 HEAD 的移動歷史:git reflog

查看其他引用的 reflog

reflog 默認查看 HEAD 的移動歷史,除此之外,也可以手動加上名稱來查看其他引用的移動歷史:git reflog master

額外說點:.gitignore——排除不想被管理的文件和目錄

.gitignore記錄了所有你希望被 Git 忽略的目錄和文件。


image.png

Git原理詳解及實用指南

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,978評論 2 374

推薦閱讀更多精彩內容

  • GIT分布式版本控制系統最佳實踐 這篇文章來自于老男孩教育高級架構師班12期的徐亮偉同學。 首先感謝老男孩架構師班...
    meng_philip123閱讀 3,455評論 4 36
  • 第1章 Shell和vi 1.1什么是shell 在計算機科學中,Shell俗稱殼,用來區別于Kernel(核),...
    福爾摩雞閱讀 955評論 0 1
  • git常用命令 GIT常用命令備忘:http://stormzhang.com/git/2014/01/27/gi...
    新篇章閱讀 8,529評論 1 26
  • 近代大文豪錢鐘書先生的知識是非常淵博的,錢老看過的文章可以過目不忘,可能與錢老在讀書中非常喜歡做讀書筆記有...
    學習與成長杜彥龍閱讀 1,474評論 0 2
  • 9月5號 今天是可可心心念念開學的日子,一大早我就喊她起來吃飯,她起床后坐在那里發呆,讓她吃飯,說是不餓吃不下!我...
    人間十六月閱讀 337評論 0 2