1 從服務器上克隆完整的Git倉庫(包括代碼和版本信息)到本機上。2 在自己的機器上根據不同的開發(fā)目的,創(chuàng)建分支,修改代碼。3 在單機上自己創(chuàng)建的分支上提交代碼、合并分支,提交到本地版本庫。4 把服務器上最新版的代碼pull/fetch下來,解決服務器版本庫與本地代碼的沖突,然后跟自己的主分支合并。5 如果沒問題,push到服務器
如果中央服務器故障,Git本地倉庫包含代碼庫還有歷史庫,不需要網絡,自己可以在脫機環(huán)境查看開發(fā)的版本歷史,在本地的環(huán)境開發(fā)也可以進行比對,回退等操作。Git都在本地保存了版本記錄,所以大家合并起來就容易多了,等到服務器好了,直接提交就行了;或者可以隨時創(chuàng)建一個新的中央庫,隨便從其他人那里復制一個然后同步就立刻恢復了中央庫。
Git把數據看作是對小型文件系統(tǒng)的一組快照。
每次你提交更新,或保存項目狀態(tài)時,它主要對當時的全部文件制作一個快照并保存這個快照的索引。
為了高效,如果文件沒有修改,Git 不再重新存儲該文件,而是只保留一個鏈接指向之前存儲的文件。
Git概念理解
Git工作區(qū)域種類:
工作區(qū)(工作目錄):電腦里能看到的目錄
版本庫(?Git 倉庫目錄):工作區(qū)有一個隱藏目錄.git,就是Git的版本庫。
暫存區(qū)域:一個文件,保存了下次將提交的文件列表信息,一般在 Git 倉庫目錄中。
有時候也被? 稱作`索引',不過一? 般說法還是叫暫存區(qū)域。

被管理文件的幾種狀態(tài):
已修改(modified):表示修改了文件,但還沒保存到本地版本庫中
已暫存(staged):表示對一個已修改文件的當前版本做了標記,使之包含在下次提交的快照中
已提交(committed):表示數據已經安全的保存在本地版本庫中
Git 工作流程:在工作目錄中修改文件 à 暫存文件à將文件的快照放入暫存區(qū)域 à 提交更新,找到暫存區(qū)域的文件,將快照永久性存儲到
Git 倉庫目錄。
下載安裝
1 從Git官網直接 https://git-scm.com/downloads下載安裝程序
2 安裝完成后,命令行輸入“git
--version”,顯示如下信息表示安裝成功。

3 設置用戶信息,用戶名稱與郵件地址,每一個Git的提交都會使用這些信息,并且它會寫入到你的每一次提交中,不可更改
$ git config --global user.name "Your Name"
$ git config --global user.email "? email@example.com "
注意git config命令的--global參數,用了這個參數,表示你這臺機器上所有的Git倉庫都 會使用這個配置,當然也可以對某個倉庫指定不同的用戶名和Email地址。
4 檢查配置信息
git config --list
Git倉庫
什么是Git倉庫??
可以簡單理解成一個目錄,這個目錄里面的所有文件都可以被Git管理起來,每個文件的修改、刪除,Git都能跟蹤,以便任何時刻都可以追蹤歷史,或者在將來某個時刻可以“還原”。
把想讓git管理的文件放入此倉庫下,放到其他地方Git再厲害也找不到你想管理的文件
創(chuàng)建Git倉庫
有兩種方法創(chuàng)建Git倉庫
1 通過$ git init命令在現(xiàn)有目錄中初始化倉庫
該命令將創(chuàng)建一個名為?.git?的子目錄,這個子目錄含有你初始化的Git倉庫中所有的必須文件,就是Git的版本庫。
? 如果你是在一個已經存在文件的文件夾(而不是空文件夾)中初始化Git倉庫的話,
文件并不會被跟蹤,通過git add?命令來實現(xiàn)對指定文件的跟蹤,然后執(zhí)行git
commit提交
創(chuàng)建Git倉庫
2 從一個服務器克隆一個現(xiàn)有的 Git 倉庫
$ git clone https://github.com/test/test
在當前目錄下創(chuàng)建一個名為“test”的目錄,并在這個目錄下初始化一個?.git?文件夾,從遠程倉庫拉取下所有數據放入?.git?文件夾,然后從中讀取最新版本的文件的拷貝。
如果進入到這個新建的“test”文件夾,發(fā)現(xiàn)所有的項目文件已經在里面了,并且都被git管理起來了,直接使用即可,無需執(zhí)行add和commit命令。
也可以自定義本地倉庫的名字,使用如下命令:
$ git clone https://github.com/test/test myTest
結果和上一個命令結果相同的,只是本地創(chuàng)建的倉庫名字變?yōu)閙yTest。
Git 支持多種數據傳輸協(xié)議。上面使用的是?https://?協(xié)議,也可以使用?git://?協(xié)議或者使用
SSH
傳輸協(xié)議,比如?user@server:path/to/repo.git?,主要看git服務器的配置。
理解git文件的生命周期
工作區(qū)下的每一個文件分兩種狀態(tài)
已跟蹤:指那些被加入了版本控制的文件,在上一次快照中有它們的記錄,工作一段時間后,它們的狀態(tài)可能處于未修改,已修改或已放入暫存區(qū)。
未跟蹤:工作區(qū)中除已跟蹤文件以外的所有其它文件,它們既不存在于上次快照的記錄中,也沒有放入暫存區(qū)
初次克隆某個倉庫的時候,工作目錄中的所有文件都屬于已跟蹤文件,并處于未修改狀態(tài)
查看文件狀態(tài)
$ git status
沒有任何文件的打印結果

將文件添加到git版本庫
$ git add xxx
git add?命令使用文件或目錄的路徑作為參數,如果參數是目錄的路徑,該命令將遞歸地跟蹤該目錄下的所有文件。
使用命令?git add?開始跟蹤一個文件,即把文件加入到git版本庫的暫存區(qū),將此文件變?yōu)橐迅?/p>

被跟蹤文件進入暫存狀態(tài),如果此時提交,那么該文件此刻的版本將被留存在版本庫中。

暫存已修改文件
$ git add xxx
現(xiàn)在我們新建一個XXX.txt文件,并通過add命令將其設置為被跟蹤,然后再修改XXX.txt文件內容。
Changes not staged for commit表示說明已跟蹤文件的內容發(fā)生了變化,但還沒有放到暫存區(qū)。
要暫存這次更新,需要運行?git
add?命令
$git add這是個多功能命令:
1 可以用它開始跟蹤新文件
2把已跟蹤的文件放到暫存區(qū)
Git add注意事項
如果你現(xiàn)在提交,那么提交的版本是你最后一次運行?git
add?命令時的那個版本,而不是在工作目錄中的當前版本。所以,運行了?git
add?之后又作了修訂的文件,需要重新運行?git
add?把最新版本重新暫存起來
忽略文件
一般我們總會有些文件無需納入 Git 的管理,也不希望它們總出現(xiàn)在未跟蹤文件列表(比如日志文件,或者編譯過程中創(chuàng)建的臨時文件等)
創(chuàng)建一個名為?.gitignore?的文件,列出要忽略的文件模式
$ cat .gitignore
*.[oa]
*~
第一行告訴 Git 忽略所有以?.o?或?.a?結尾的文件。
第二行告訴 Git 忽略所有以波浪符(~)結尾的文件
tips:GitHub已經為我們準備了各種配置文件
https://github.com/github/gitignore
文件?.gitignore?的格式規(guī)范如下:
1 所有空行或者以?#?開頭的行都會被 Git 忽略。
2 可以使用標準的 glob 模式匹配。
3 匹配模式可以以(/)開頭防止遞歸。
4 匹配模式可以以(/)結尾指定目錄。
5 要忽略指定模式以外的文件或目錄,可以在模式前加上驚嘆號(!)取反。
所謂的 glob 模式是指 shell
所使用的簡化了的正則表達式
1 星號(*)匹配零個或多個任意字符
2 [abc]匹配任何一個列在方括號中的字符
? (這個例子要么匹配一個a,要么匹配一個b,要么匹配一個c)
3 問號(?)只匹配一個任意字符;
4 如果在方括號中使用短劃線分隔兩個字符,表示所有在這兩 ?個字符范圍內的都可以匹配
? (比如?[0-9]?表示匹配所有0 到 9 的數字)
5 使用兩個星號(*) 表示匹配任意中間目錄
? (比如`a/**/z`可以匹配?a/z,?a/b/z?或 `a/b/c/z`等)
查看已暫存和未暫存的修改
$ git diff?&&$ ?git diffxxx
git diff 命令使用文件作為參數
此命令比較的是工作目錄中當前文件和暫存區(qū)域快照之間的差異,
也就是修改之后還沒有暫存起來的變化內容。
將文件提交到git版本庫
$ git commit –m “xxxxxxxxxxxxxxx”
使用命令?git
commit把暫存區(qū)的文件提交到git版本庫;
-m后面輸入的是本次提交的說明,可以輸入任意內容,最好是有意義的,這樣你就能從歷史記錄里方便地找到改動記錄
tips:在此之前,請一定要確認還有什么修改過的或新建的文件還沒有git
add過,否則提交的時候不會記錄這些還沒暫存起來的變化,這些修改過的文件只保留在本地磁盤。
所以,每次準備提交前,先用?git
status?看下,是不是都已暫存起來了, 然后再運行提交命令?git commit
重新將文件提交到git版本庫
$ git commit –amend –m “xxxxxxxx”
有時候提交完了發(fā)現(xiàn)漏掉了幾個文件沒有添加,或者提交信息寫錯了。此時,可以運行帶有?--amend?選項的提交命令嘗試重新提交。
這個命令會將暫存區(qū)中的文件提交。
如果自上次提交以來你還未做任何修改(例如,在上次提交后馬上執(zhí)行了此命令),那么快照會保持不變,而你所修改的只是提交信息
跳過使用暫存區(qū)域
$ git commit –a –m “xxxxxxxxxxxxxxx”
每次提交文件都需要git addàgit
commit,有沒有更簡單的方式呢?
給?git
commit?加上?-a?選項,Git 就會自動把所有已經跟蹤過的文件暫存起來一并提交,從而跳過?git
add?步驟
查看已暫存和版本庫的修改
$ git diff –-cached(staged?)? &&?git diff –-cached(staged?)xxx
此命令比較的是暫存區(qū)域快照和版本庫之間的差異
移除文件
$ git rm xxx
git rm命令使用文件或者目錄的名字,也可以使用?glob?模式
要從 Git 中移除某個文件,就必須要從已跟蹤文件清單中移除,然后提交。
可以用git rm命令完成此項工作,并連帶從工作目錄中刪除指定的文件,這樣以后就不會出現(xiàn)在未跟蹤文件清單中了。
簡單地從工作目錄中手工刪除文件,運行?git
status?時就會在 “Changes not staged for commit” 部分(也就是?未暫存清單)看到
$ git rm –-cached xxx
把文件從 Git 倉庫中刪除,仍然保留在當前工作目錄中,換句話說,你想讓文件保留在磁盤,但是并不想讓
Git 繼續(xù)跟蹤,比如你忘記添加?.gitignore?文件,不小心把.class這樣的編譯生成文件添加到暫存區(qū)時
重命名文件
$ git mv xxx1?xxx2
其實,運行?git
mv?就相當于運行了下面三條命令:
$ mv README.md README
$ git rm README.md
$ git add README
查看提交歷史
$ git log
工作一段時間之后,如果你想查看提交歷史,可以使用git
log命令
按提交時間列出所有的更新,最近的更新排在最上面。
會列出每個提交的 SHA-1 校驗和、作者的名字和電子郵件地址、提交時間以及提交說明
查看提交歷史的其他格式
$ git log --pretty=oneline 顯示每次提交的簡略信息
$ gitlog –p? 顯示每次提交的內容差異,可以加上-1來僅顯示最近一次提交,除了顯示基本信息之外,還附帶了每次commit的變化
$ git log ?--stat ?顯示每次提交的簡略的統(tǒng)計信息
$ git log --since=2.weeks? 列出所有最近兩周內的提交,可以設置多種格式,比如說具體的某一天?“2008-01-15”,或者是相對地多久以前?“2years
1 day 3 minutes ago”。
暫存區(qū)和版本庫回退
$ git reset HEAD xxxxxxx&&? $gitreset HEAD^ ?
git reset 命令使用文件作為參數,或者用^?
上一個版本就是HEAD^,上上一個版本就是HEAD^^,往上100個版本HEAD~100 reset HEAD xxxx
暫存區(qū)回退 $ git reset HEAD xxxxxxx
暫存區(qū)和版本庫回退 $ gitreset HEAD^?
$ git reset --hard HEAD^
版本庫回退
--hard會讓工作區(qū)的文件一起回退
版本找回
$ git reset --hard 1094a
參數為commit id? 1094a,版本號沒必要寫全,前幾位就可以了,Git會自動去找
版本回退之后用git
log是再也找不到提交歷史了,也就無法找到commit id,
這個時候可以用git reflog來查看你的每一次命令
撤消工作區(qū)修改
$ git checkout –
xxxx
參數為文件
如果你并不想保留對?xxx.txt?文件的修改怎么辦?
該如何方便地撤消修改 ,將它還原成上次提交時的樣子(剛克隆完的樣子,剛把它放入工作目錄時的樣子)?
xxx修改后還沒有被放到暫存區(qū),撤銷修改就回到和版本庫一模一樣的狀態(tài);
其實是用版本庫里的版本替換工作區(qū)的版本,無論工作區(qū)是修改還是刪除,都可以“一鍵還原”。
Git分支
Git和傳統(tǒng)的版本控制工具最大的區(qū)別在于分支,學習分支才能說是真正的掌握git的使用。
其他版本控制工具都有分支管理,但是用過之后你會發(fā)現(xiàn),這些版本控制系統(tǒng)創(chuàng)建和切換分支很慢,但是在git上,無論創(chuàng)建、切換和刪除分支,Git都很快完成。
大多數版本控制系統(tǒng)在創(chuàng)建分支時,將所有的項目文件都復制一遍,并保存到一個特定的目錄。
完成這樣的過程通常需要好幾秒鐘,有時甚至需要好幾分鐘,項目越大,所需時間的越長。
在 Git 中,基于Git的數據存儲方式,任何規(guī)模的項目都能在瞬間創(chuàng)建新分支,而且分支合并也同樣的簡單和快速。
所以使用Git,鼓勵頻繁地創(chuàng)建和使用分支做不同的任務。
Git分支基礎知識
我們假設現(xiàn)在有一個工作目錄,里面包含了三個將要被暫存和提交的文件。
暫存操作會為每一個文件計算校驗和(SHA-1 哈希算法),然后會把當前版本的文件快照保存到 Git 倉庫中(Git 使用
blob
對象來保存它們),最終將校驗和加入到暫存區(qū)域等待提交

當使用?git
commit?進行提交操作時,Git 會先計算每一個子目錄的校驗和,然后在
Git 倉庫中這些校驗和保存為樹對象。
隨后,Git 便會創(chuàng)建一個提交對象,該提交對象會包含一個指向快照的指針,還包含了作者的姓名和郵箱、提交時輸入的信息、指向它的父對象的指針以及包含指向這個樹對象的指針。


每次提交,Git 會保存一個提交對象,多次提交之后,那么這次產生的提交對象會包含一個指向上次提交對象(父對象)的指針

每次提交,Git都把它們串成一條時間線。
截止到目前,只有一條時間線,在Git里,?這個分支叫主分支(master),就是GIt默認分支,它就跟其它分支完全沒有區(qū)別。
Git 的分支,本質上是指向提交對象的可變指針
Git 是怎么知道當前在哪一個分支上?
很簡單,它有一個名為?HEAD?的特殊指針,可以將?HEAD?想象為當前分支的別名,HEAD指向的就是當前分支。
一開始的時候,master分支是一條線,Git用master指向最新的提交,再用HEAD指向master,
就能確定當前分支,以及當前分支的提交點:

每次提交(commit),master分支都會向前移動一步,隨著你不斷提交,master分支的線也越來越長

Git分支理解
當我們創(chuàng)建新的分支,例如dev時,Git新建了一個指針叫dev,指向master相同的提交,
通過checkout命令再把HEAD指向dev,就表示當前分支在dev上:

從現(xiàn)在開始,對工作區(qū)的修改和提交就是針對dev分支了,
提交一次(commit),dev指針往前移動一步,而master指針不變

假如我們在dev上的工作完成了,我們切換到master分支的時候,可以看到工作區(qū)文件是之前的
樣子,所以切換分支不僅使HEAD指回master?分支,而且將工作目錄恢復成?master?分支所指向的快照內容

現(xiàn)在我們可以把dev合并到master上,合并就是把master指向dev的當前提交,就完成了合并:

合并完分支后,可以刪除dev分支。
刪除dev分支就是把dev指針給刪掉,刪掉后,我們就剩下了一條master分支

Git分支操作
1 創(chuàng)建分支,要確定在哪個分支上創(chuàng)建子分支
$ git checkout -b dev
查看當前分支,當前分支前面會標一個*號
$ git branch

現(xiàn)在在dev分支上正常提交,比如對hellodongnao.txt做個修改,加上一行,然后提交

3現(xiàn)在我們需要將dev分支合并到master分支
? 現(xiàn)在切換到master分支上,查看文件還是master之前的提交狀態(tài),因為那個提交是在dev分支上,而master分支此刻的提交點并沒有變。
$ git merge dev
git merge命令用于合并指定分支到當前分支

合并后,再查看文件內容,就可以看到,和dev分支的最新提交是完全一樣的。
4 合并完成后,可以刪除dev分支了
$ git branch -d dev
分支沖突解決
合并操作不會如此順利,
如果你在兩個不同的分支中,對同一個文件的同一個部分進行了不同的修改,合并它們就會出問題。
現(xiàn)在我們重復上面分支的操作
1 創(chuàng)建一個devOne分支
2 在devOne分支上進行修改和提交操作
3 切換回master分支,對同一個文件進行修改和提交操作
4 合并devOne分支
5 刪除devOne分支
HEAD指向master?分支,在=======?的上半部分,而?devOne分支在?=======?的下半部分。
你可以選擇使用由?=======分割的兩部分中的一個,也可以自行合并這些內容。

分析問題出現(xiàn)的原因:既在devOne分支上做了修改提交,也在master分支上對同一文件做了提交,導致合并devOne分支的時候出現(xiàn)了問題。
發(fā)生沖突了怎么辦?
hello.txt合并發(fā)生了沖突,手動解決后,對每個文件使用?git add?命令來將其標記為沖突已解決沖突再提交。

非Fast forward合并
$ git merge --no-ff
-m “xxxxxx" devTwo
因為本次合并要創(chuàng)建一個新的commit,所以加上-m參數,把commit描述寫進去
我們之前說的合并分支時,Git會用Fast
forward模式,但這種模式下,刪除分支后,會丟掉分支信息。
現(xiàn)在我們不用Fast
forward模式,Git就會在merge時生成一個新的commit,這樣,從分支歷史上就可以看出分支信息。
1 創(chuàng)建一個devTwo分支
2 在devTwo分支上進行修改和提交操作
3 切換回master分支,用非Fast
forward的方式合并devTwo分支
4 刪除devTwo分支
$ git log --graph --pretty=oneline --abbrev-commit
查看分支歷史合并情況

用Fast forward模式,分支歷史上就可以看出分支提交信息和分支的信息

自動非Fast forward合并
Git也會自動使用非Fast forward模式,如分支分叉的情況,git會自動使用非fast模式

這和之前合并?devTwo分支的時候看起來有一點不一樣,開發(fā)歷史從一個更早的地方開始分叉開來。
所以Git 幫我們做了一些額外的工作,出現(xiàn)這種情況的時候,Git 會使用兩個分支的末端所指的快照以及這
兩個分支的工作祖先(分叉點),做一個簡單的三方合并。
Git也會自動使用非Fast forward模式,如分支分叉的情況,git會自動使用非fast模式

rebase
Git中除了合并,還有一種方式可以進行分支合并,就是rebase,你可以使用?rebase?命令將某一分支上(devRebase)的所有修改都移至另一分支上(master)
$ git checkout devRebase
$ git rebase master
1 首先找到這兩個分支(當前分支?devRebase 、變基操作的目標分支master)的最近共同祖先?a6081ce
2 對比當前分支相對于該祖先的全部提交,提取出來存為臨時文件,相當于刪除這些提交,在歷史中也查不到信息了
3 然后將當前分支devRebase指向目標xx1,
最后將之前另存為臨時文件的修改依序應用,生成新的提交xx2。

tips:此時下面虛線部分的東西已經沒有了,392aa重新提交變成了xx2,現(xiàn)在提交變成了直線。
$ git checkout master
$ git merge devRebase
現(xiàn)在回到?master?分支,進行一次快進合并。

在rebase的過程中,也許會出現(xiàn)沖突。Git會停止rebase并會讓你去解決沖突;
在解決完沖突后,需要執(zhí)行git
add命令標記為以解決, 不需要執(zhí)行?git commit
$ git rebase --continue
這樣git會繼續(xù)應用(apply)余下的補丁。
可以用--abort參數來終止rebase的操作,并且分支會回到rebase開始前的狀態(tài)
$ git rebase --abort
Rebase優(yōu)點
變基使得提交歷史更加整潔,向遠程分支推送時能保持提交歷史的整潔。
你首先在自己的分支里進行開發(fā),當開發(fā)完成時你需要先將你的代碼變基到origin/master上,
然后再向主項目提交修改。
這樣的話,項目的維護者就不再需要進行整合工作,只需要快進合并。
使用的時候要注意,不要對在你的倉庫外有副本的分支執(zhí)行變基!
變基操作的實質是刪除一些現(xiàn)有的提交,然后相應地新建一些內容一樣但實際上不同的提交。如果你已經將提交推送至某個倉庫,而其他人也已經從該倉庫拉取提交并進行了后續(xù)工作,此時,如果你用?git
rebase?命令重新整理了提交并再次推送,你的同事因此將不得不再次將他們手頭的工作與你的提交進行整合,接下來你還要拉取并整合他們修改過的提交。
Rebase與非Fast forward對比

變基是將一系列提交按照原有次序依次應用到另一分支上,而合并是把最終結果合在一起。
理解變基就是將提交變成直線,然后直接快速合并。
注意無論是通過變基,還是通過非fast合并,整合的最終結果所指向的快照始終是一樣的,只不過提交歷史不同罷了。
到底合并還是變基好?
1 如果你想看倉庫的提交歷史記錄實際發(fā)生過什么,就算合并產生的提交歷史是一團糟也沒關系,
覺得它是歷史文檔,不能亂改,能隨時查閱發(fā)生的事情,那就用非fast方式。
2 如果認為提交歷史是項目過程中發(fā)生的事,只看結果,方便查閱,就用rebase。
所以看你和團隊的需求
建議是對未推送給別人的本地修改執(zhí)行變基操作清理歷史,對已推送至別處的提交不要執(zhí)行變基操作
暫存分支
$ git stash
當程序出現(xiàn)bug時,你就需要新建一個臨時分支來修復,修復后,合并分支,然后將臨時分支刪除,但是你當前還在子分支上進行的工作還沒有提交,而且只開發(fā)到一半,還不能提交。但是bug需要緊急修復,這個時候怎么辦?
Git提供了一個stash功能,可以把當前分支暫存起來,之后可以恢復繼續(xù)開發(fā)
現(xiàn)在我們創(chuàng)建一個子分支來修復bug。
1首先確定要在哪個分支上修復bug,假定需要在master分支上修復,就從master創(chuàng)建分支

2 現(xiàn)在修復bug,需要把“hello devTwo
branch”改為“hello devTwo branch
to bug”,然后提交:

3 修復完成后,切換到master分支并合并bug001分支
4 刪除bug001分支
Bug修復完成了,我們回到devThree分支繼續(xù)之前的開發(fā)
1 查看我們的暫存分支
$ git stash list
2 恢復我們的暫存分支
? a:一是用gitstash apply xxx恢復,stash內容并不刪除,還需要git stash
drop來刪除;
? b:另一種方式是用gitstash pop,恢復的同時把stash內容也刪了:
3 我們接著完成devThree的工作
刪除已經提交(未合并)的分支
$ git branch -D xxxxx
1 我們新建了 一個分支,已經完成了并提交(commit)的開發(fā),但是這個時候不需要此需求了,應該把此分支刪除。
補丁patch
補丁并不是針對所有代碼的修改,只是針對于局部的修改。
在代碼的維護中,如果只修改一部分代碼,需要將代碼完整的克隆下來,可是修改的只是很小的一部分;在這種情況下可以將一些代碼的補丁信息發(fā)送給開發(fā)者,開發(fā)者收到之后知道那些代碼被修改了,這樣就可以使用一個極低的開銷實現(xiàn)代碼的修改操作
在git中提供了兩種補丁方式
? 1使用gitdiff生成標準的patch
? 2 使用git format-patch聲明git專用的patch
Git diff生產標準的patch
A 貢獻者
1 創(chuàng)建一個testPatchDiff分支
2 在testPatchDiff分支上進行代碼修改
3 使用git diff xx 查看修改
4 在testPatchDiff分支上進行提交
5 使用git diff master> testDiff創(chuàng)建補丁信息testDiff
6 刪除testPatchDiff分支
B 開發(fā)者
? ? 1 cat testDiff查看有哪些修改
2 切換到master分支
3 創(chuàng)建一個新的applyPatchDiff分支
4 使用git apply testDiff 應用補丁信息testDiff
5在applyPatchDiff分支上進行提交補丁操作
6 切換回master分支合并applyPatchDiff分支
7 刪除applyPatchDiff分支
git format-patch聲明git專用的patch
A 貢獻者
1 創(chuàng)建一個testPatchFormat分支
2 在testPatchFormat分支上進行代碼修改
3 使用git diff xx 查看修改
4 在testPatchFormat分支上進行提交
5 使用git format-patch master與原始代碼做一個比較,比較之后會自動生成補丁文件
???? 6刪除testPatchFormat分支
B 開發(fā)者
???? 1cat 0001-testPathcFormat.patch查看有哪些修改(像是一封郵件,可以將文件粘貼? 進電子郵件客戶端,也可以通過命令行gitsend-email發(fā)送它)
2 切換到master分支
3 創(chuàng)建一個新的applyPatchFormat分支
4 使用git am 0001-testPathcFormat.patch應用補丁信息
5 切換回master分支合并applyPatchDiff分支
6 刪除applyPatchFormat分支
補丁兩種方式比較
git diff生成的Patch兼容性強。如果你修改的代碼不是Git管理的版本庫,那么必須使用git
diff生成的patch才能讓你的代碼被項目的維護人接受。
但是如果你是向公共的開發(fā)社區(qū)進行代碼的補丁更正,建議使用git format-patch,這樣不僅標準,而且也可以將作者的信息公布
GitFlow理解
GitFlow 是由
Vincent
Driessen 提出的一個
git操作流程標準,包含如下幾個關鍵分支:
master:主分支,非常穩(wěn)定的,不用來開發(fā)和發(fā)布,只用來跟蹤已經發(fā)布的代碼;
develop:主開發(fā)分支,包含確定即將發(fā)布的代碼;開發(fā)都在這個分支;
? ? 到發(fā)布時,再合并到release上;
feature:新功能分支,一般一個新功能對應一個分支,對于功能的拆分需要比較合理,以? 避免一些后面不必要的代碼沖突;
release:發(fā)布分支,發(fā)布時候用的分支,測試時候發(fā)現(xiàn)的
bug直接 在這個分支進行修復;
hotfix:緊急修 bug
的時候用;

我們想在開發(fā)要開發(fā)一個新功能,基于develop分支創(chuàng)建feature分支
完成后再合并到 develop 分支上,等待發(fā)布

當需要發(fā)布時,我們從 develop 分支創(chuàng)建一個 release 分支?
然后這個 release 分支會發(fā)布到測試環(huán)境進行測試,如果發(fā)現(xiàn)問題就在這個分支直接進行修復。

發(fā)布結束后,這個 release 分支會合并到
develop
和 master
分支,從而保證不會有代碼丟失

hotfix 分支的作用是緊急修復一些 Bug。它們都是從
master
分支上建立,修復結束后再合并到
develop
和 master
分支上。
GitFlow的好處
并行開發(fā):
每個新功能都會建立一個新的 feature分支,從而和已經完成的功能隔離開來,而且只有在新功能完成開發(fā)的情況下,其對應的 feature分支才會合并到主開發(fā)分支(develop分支)
協(xié)作開發(fā):
每個 feature分支多人協(xié)同開發(fā)。
發(fā)布階段:
當 feature 開發(fā)完成的時候,它會被合并到 develop 分支,這個分支主要用來暫時保存那些還沒有發(fā)布的內容,所以如果需要再開發(fā)新的 feature,我們只需要從 develop 分支創(chuàng)建新分支,即可包含所有已經完成的 feature 。
緊急修復:
hotfix(bug) 分支,這種類型的分支是從master分支上創(chuàng)建出來并做一個緊急的修復,而且這個緊急修復只影響這個已經發(fā)布的 版本,而不會影響到你正在開發(fā)的新 feature。
Git遠程倉庫
GitHub是一個免費的服務器,這個網站就是提供Git倉庫托管服務的,所以,只要注冊一個GitHub賬號,就可以免費獲得Git遠程倉庫
?注意GitHub上免費托管的Git倉庫,任何人都可以看到
有了GitHub帳號之后,并不是說就可以直接使用了,還需要創(chuàng)建SSH
Key。
1 在用戶主目錄下,看看有沒有.ssh目錄,如果有,再看看這個目錄下有沒有id_rsa和id_rsa.pub這兩個文件,如果已經有了,可直接跳到下一步。如果沒有,打開Git
Bash,創(chuàng)建SSH Key:
$ ssh-keygen -t rsa -C "youremail@xxx.com"

里面有id_rsa和id_rsa.pub兩個文件,這兩個就是SSH Key的秘鑰,id_rsa是私鑰,id_rsa.pub是公鑰
2 登陸GitHub,打開“Account settings”,“SSH and GPG keys”頁面:
然后,點“New Ssh key”,填上任意Title,在Key文本框里粘貼id_rsa.pub文件的內容
那么此時表示已經和GitHub之間建立好了一個安全鏈接。
由于ssh存在,GitHub才能進行用戶識別。
GitHub允許你添加多個Key。
添加遠程庫
在本地創(chuàng)建了一個Git倉庫后,又想在GitHub創(chuàng)建一個Git倉庫,并且讓這兩個倉庫進行遠程同步,這樣,GitHub上的倉庫既可以作為備份,又可以讓其他人通過遠程倉庫來協(xié)作。
1首先,登陸GitHub,然后,在右上角找到“Create a new repo”按鈕,創(chuàng)建一個新的倉庫。
2 在Repository name填入testGit,其他保持默認設置,點擊“Create repository”按鈕,就成功地創(chuàng)建了一個新的Git倉庫
現(xiàn)在設置的倉庫名稱為testGit,倉庫創(chuàng)建完成之后會給出兩種鏈接方式
a: https://github.com/xx/testGit.git
b: git@github.com:xx/testGit.git
使用https除了速度慢以外,還有個最大的麻煩是每次推送都必須輸入口令,但是在某些只開放http端口的公司內部就無法使用ssh協(xié)議而只能用https。
3目前,在GitHub上的這個testGit倉庫還是空的,GitHub告訴我們,可以從這個倉庫克隆出新的倉庫,也可以把一個已有的本地倉庫與之關聯(lián)。
現(xiàn)在,把GiuHub與本地倉庫關聯(lián),在本地的testGit倉庫下運行命令
$ git remote add origin git@github.com:xxxxxxx/testGit.git
xxxxx為你自己的GitHub帳號
遠程庫倉庫的名字就是origin,這是Git默認的叫法,也可以改成別的
此時已經和遠程倉庫建立了鏈接,但是遠程倉庫里面并沒有本地倉庫的內容
4 下一步,就可以把本地庫的所有內容推送到遠程庫上:
$ git push -u origin master
把本地庫的內容推送到遠程,用git push命令,實際上是把當前分支master推送到遠程。
由于遠程庫是空的,我們第一次推送master分支時,加上了-u參數,Git不但會把本地的master分支內容推送的遠程新的master分支,還會把本地的master分支和遠程的master分支關聯(lián)起來,在以后的推送或者拉取時就可以簡化命令以后直接運行
$ git push origin master
把本地master分支的最新修改推送至GitHub
5 查看GitHub是有添加了本地內容
tips:當你第一次使用Git的clone或者push命令連接GitHub時,會得到一個警告:
? Theauthenticity of host 'github.com (xx.xx.xx.xx)'
can't be established.
? RSAkey fingerprint isxx.xx.xx.xx.xx.
? Areyou sure you want to continue connecting (yes/no)?
這是因為Git使用SSH連接,而SSH連接在第一次驗證GitHub服務器的Key時,
需要你確認GitHub的Key的指紋信息是否真的來自GitHub的服務器,輸入yes回車即可。
這個警告只會出現(xiàn)一次,后面的操作就不會有任何警告了
提交文件到遠程倉庫
1 修改xxx.txt并提交
2 此時的修改都屬于本地倉庫master分支,下面提交到遠程倉庫master分支
$ git push origin master
遠程倉庫其他操作
使用https建立一個test遠程倉庫?
$ git remote add test?https://github.com/xxxxx/xxxGit.git
查看遠程倉庫信息,如果沒有推送權限,就看不到push的地址
$ git remote?&&? $gitremote -v
切換遠程倉庫
$ git remote set-url
origin git@github.com:xxxxx/xxxGit.git
刪除遠程倉庫
$ git remote rm? test
從遠程庫克隆
之前先有本地庫,后有遠程庫的時候,如何關聯(lián)遠程庫。
現(xiàn)在先創(chuàng)建遠程庫,然后,從遠程庫克隆。
1 首先,登陸GitHub,然后,在右上角找到“Create
a new repo”按鈕,創(chuàng)建一個新的倉庫helloGit。
我們勾選Initialize this repository with a README表示自動為用戶進行倉庫的初始化,并且這樣GitHub會自動為我們創(chuàng)建一個README.md文件。
2 現(xiàn)在,遠程庫已經準備好了,下一步是用命令git
clone克隆一個本地庫,不要在xxxGit目錄下操作,直接換一個新目錄helloGit。
$ git clone git@github.com:xxxxx/helloGit.git
3 再嘗試下提交文件到遠程倉庫
克隆其他開源項目
不要認為GitHub就是一個遠程倉庫,它上面有不少開源項目,如bootstrap,mybatis
? 如:https://github.com/mybatis
1 但是這個上面下載下來的代碼是不能夠進行修改的,因為這個主文件只能由用戶發(fā)出補丁,而后由開發(fā)者進行修改。如果要是參考源碼或者修改,可以將項目克隆過來(fork)
2 進入自己的帳號下,獲取到遠程倉庫的地址,之后可以在本地倉庫中將代碼克隆下來。
$ git clone git@github.com:xxxxx/mybatis.git
tips:如果從mybatis的作者的倉庫地址克隆,因為沒有權限,你將不能推送修改。
協(xié)同開發(fā)
單分支開發(fā)
? ? 1 A修改其中一個文件并commit和push
? 2 B修改另外一個文件并commit和push(能不能push成功?)
兩個開發(fā)者并沒有編輯同一個文件,但Git要求在本地合并提交。B必須抓取A的改動并合并它們,才能被允許推送。?
$ git fetch <遠程主機名>
//這個命令將某個遠程主機的更新全部取回本地
$ git fetch <遠程主機名>
<分支名> //取回特定分支的更新,可以指定分支名
3 B執(zhí)行fetch取回服務器的更新(可以通過git
log –p FETCH_HEAD查看更新信息)

4 B合并遠程分支到自己的master分支
$git merge origin/master

6 于此同時A還在開發(fā),commit之后準備push
7 A想要push,也得先執(zhí)行fetch拉取服務器的更新并合并再提交

分支其他操作
分支更名
$ git branch –m xxx1 xxx2? xxx1為原來分支名稱,xxx2為新分支名稱
查看分支
$ git brance –a ?查看全部分支,包括遠程和本地
$ git brance –r??查看遠程分支
$ git brance –l??查看本地分支
刪除遠程分支
$ git push origin --delete xxxxx
標簽
發(fā)布一個版本時,我們通常先在版本庫中打一個標簽(tag),這樣,就確定了打標簽時刻的版本。將來無論什么時候,取某個標簽的版本,就是把那個打標簽的時刻的歷史版本取出來。所以,標簽也是版本庫的一個快照。
Git的標簽雖然是版本庫的快照,但其實它就是指向某個commit的指針(但是分支可以移動,標簽不能移動),所以,創(chuàng)建和刪除標簽都是瞬間完成的。

創(chuàng)建標簽
在Git中打標簽非常簡單,首先,切換到需要打標簽的分支上

$ git tag xxxx
默認標簽是打在最新提交的commit上的。如果想在之前的commit上打標簽,先找到歷史提交的commit
id,然后打上就可以了:
$ git tag v0.9 67cda3
可以用命令git
tag查看所有標簽:
$ git tag
還可以創(chuàng)建帶有說明的標簽,用-a指定標簽名,-m指定說明文字:
?$git tag -a xxxx -m “xxxxx" xxxxx
查看標簽信息
$ git show xxx
操作標簽
本地標簽刪除
$ git tag -d xxxx

推送本地標簽到gitHub
$ git push origin xxxx
推送全部尚未推送到遠程的本地標簽
$ git push origin --tags
刪除遠程倉庫標簽
1 先刪除本地標簽
$ git tag -d xxxx
2 從遠程刪除
$ git push origin :refs/tags/xxxxxx
搭建GitLab服務器
GitHub是一個免費的服務器,這個網站就是提供Git倉庫托管服務的,如果公司開發(fā)使用的話,會有幾個問題
? 1網絡不穩(wěn)定
? 2代碼是公開的,大家都可以查看
如果你需要一個私有的托管服務,支付每個月7美元購買5個私有庫,想要更多的私有倉庫則要交更多的錢
最好的方法就是在你的服務器上運行 Git。不僅你能夠省去一筆錢,你還能夠在你的服務器有更多的操作。
在linux上有兩種方式部署git服務器
1 使用名為 GitLab 的
GUI
工具
2 運行一個純Git 服務器
GitLab 是一個非常優(yōu)秀的項目,這是一個開源項目,允許用戶在自己的服務器上運行類似于
GitHub 的項目管理系統(tǒng),使用
GitLab 為團隊成員或公司運行類似于
GitHub 的服務,可以使用
GitLab 開發(fā)私有項目。
安裝之前,請確保你的服務器是否安裝了
ssh? ? rpm -qa|grep -E
"openssh"
防火墻? rpm-qa|grep-E "firewalld"
wget? ? rpm -qa|grep -E
"wget"
1 安裝 GitLab 之前,需要配置
SMTP
電子郵件服務器,以便
GitLab 可以在需要時隨時推送電子郵件。官方推薦使用
Postfix。先在你的服務器上安裝
Postfix
# yum install postfix? 安裝命令
# systemctl enablepostfix? 開機自啟動
# systemctl startpostfix? 啟動postfix
2添加GitLab鏡像源,其他鏡像下載地址:https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/
# wget?https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-10.0.0-ce.0.el7.x86_64.rpm
3 安裝gitlab
# rpm -i
gitlab-ce-10.0.0-ce.0.el7.x86_64.rpm
4 修改gitlab配置文件指定服務器ip和自定義端口
# vim? /etc/gitlab/gitlab.rb
??? external_url?`http://192.168.1.149:8900`??? 服務器ip和未被占用的端口
??? unicorn[‘port’]=8899? ? ??? 默認8080,設置未被占用端
5 重置gitlab配置文件
# gitlab-ctl
reconfigure
6 重啟gitlab
# gitlab-ctl
restart
7 訪問gitlab,直接輸入上面配置的ip加端口訪問即可
???初始賬戶: root?密碼:5iveL!fe
8 設置gitlab發(fā)信功能,發(fā)信系統(tǒng)用的默認的postfix,smtp是默認開啟的,兩個都啟用了,兩個都不會工作,可以自己選擇
? a 設置關閉smtp,開啟postfix
# vim /etc/gitlab/gitlab.rb
???gitlab_rails['smtp_enable']
= false
b 關閉postfix,設置開啟smtp
???https://docs.gitlab.com/omnibus/settings/smtp.html
測試是否可以郵件通知:登錄并添加一個用戶,我這里使用qq郵箱添加一個用戶,登錄qq郵箱,
可以收到郵件通知(也可在linux執(zhí)行echo "test mail"|mail -s "postfix mail title"? ?123456789@qq.com)
如果收不到,請查看垃圾郵箱或者檢查郵件是否被攔截并刪除,如果有請?zhí)砑拥桨酌麊?/p>
并刪除用戶再重新添加用戶就可以收到了,否則請檢查郵件日志并做好相關設置
tips:
1 如果gitlab報502錯誤,一般是權限問題,解決方法:# chmod -R
755 /var/log/gitlab
?如果還不行,請檢查你的內存,安裝使用GitLab需要至少4GB可用內存,否則出現(xiàn)各種詭異的問題,
?而且在使用過程中也經常會出現(xiàn)500錯誤.
2 gitlab-ctl reconfigure:
? Errorexecuting
action `run` on resource 'execute[/opt/gitlab/embedded/bin/initdb-D /var/xxxx‘
?文件/etc/passwd的權限是600,給予644權限后,解決問題