$ git clone https://github.com/libgit2/libgit2
教程網站:https://git-scm.com/book/zh/v2/ javascript
*windows下的powershell命令行工具聽說很強大php
*https://help.github.com/articles/connecting-to-github-with-ssh/ [如何關聯github和本身的本地主機]html
執行ssh-add時出現Could not open a connection to your authentication agent,則只要運行以下命令便可:ssh-agent bash前端
git status沒法顯示中文文件名(八進制)java
git 默認中文文件名是 \xxx\xxx 等八進制形式,是由於 對0x80以上的字符進行quote ,只須要
git config –global core.quotepath false
core.quotepath設爲false的話,就不會對0x80以上的字符進行quote。中文顯示正常linux
關於本地修改以後,git push前 本地提交和從遠程拉取 的關係:nginx
※git pull [origin] [master]拉取時只拉取本地與遠程不一樣的部分(git push推送時也是如此),而git如何比較不一樣呢?就是經過比較 本地的commit日誌和遠程的commit日誌。因此git push前正確的順序是先在本地commit提交,而後git pull(此時git作的工做以下:git比較本地commit和遠程commit,將共同節點以後的遠程提交拉取下來和共同節點以後的本地提交合並----此時若是兩個遠程和本地都修改了同一個文件的同一行則會產生衝突,須要手動解決衝突----,合併以後的提交是最新的--即在當前遠程提交的最新提交以前--而後就能夠git push origin master了,此時將最新產生的提交push到遠程分支上)。git
※另外,若是本地修改以後先執行git pull 操做,則此時依然是比較本地的提交和遠程提交的不一樣,而後拉取不一樣的文件,此時若本地最新的提交以後的修改文件沒有涉及到遠程的須要拉取下來的文件,則此時git容許git pull拉取下來,不然則會提示共同修改的文件會被覆蓋從而放棄執行git pull(而不是嘗試合併文件,只有對已經提交的變化git纔會執行合併操做,未提交的不會),提示先執行git commit 或git stash而後再執行git pull。github
※關於git pull以後git在本地是如何合併的?正則表達式
假設遠程分支origin/master和本地分支master的最新的共同節點爲<common>, 而後本地提交了一個新的提交<local_1>,遠程上有兩個新的提交<remote_1>, <remote_2>. 而後利用git pull命令拉取,git pull的過程以下:把<remote_1>,<remote_2>拉取下來,而後把<local_1>放在<remote_2>的前面,而後再把<local_1>,<remote_1>, <remote_2>合併以後自動作一次提交放在<local_1>的前面。此時順序是: <common><remote_1><remote_2><local_1><merge>.
※git push以前必須執行git pull操做,即便別人推送到遠程倉庫中的文件和你毫無關係也必須先pull一下。也就是說,合併的操做必定是在你的本地進行的。
關於每次遠程拉取和提交都須要輸入用戶名和密碼:
緣由是在添加遠程庫的時候使用了https的方式。。因此每次都要用https的方式push到遠程庫
查看使用的傳輸協議:
git remote -v
wuxiao@wuxiao-C-B150M-K-Pro:~/MyGithub/DailyBlog$ git remote -v
origin https://github.com/toyijiu/DailyBlog.git (fetch)
origin https://github.com/toyijiu/DailyBlog.git (push)
從新設置成ssh的方式:
git remote rm origin git remote add origin git@github.com:username/repository.git git push -u origin master
再看下當前的傳輸協議:
wuxiao@wuxiao-C-B150M-K-Pro:~/MyGithub/DailyBlog$ git remote -v
origin git@github.com:toyijiu/DailyBlog.git (fetch)
origin git@github.com:toyijiu/DailyBlog.git (push)
若是你沒有拉取的倉庫的ssh網址的密碼,也能夠使用下面的解決方法:
git config --global credential.helper store
而後你會在你本地生成一個文本,上邊記錄你的帳號和密碼。而後你使用上述的命令配置好以後,再操做一次git pull,而後它會提示你輸入帳號密碼,這一次以後就不須要再次輸入密碼了。
Git:解決head detached at xxxx:
但願將同步遠程分支,執行了以下命令
git checkout origin/branch
致使HEAD指向了一個非本地的分支,進入detached-HEAD狀態,這種狀態很是危險,若是在此狀態下commit和修改代碼很容易丟失,由於並無本地分支保存你的修改
附:同步遠程分支的正確命令,如下兩個命令均可以
#這條命令能夠自定義本地branch名 git checkout -b localBranchName origin/branchName
git checkout --track origin/branchName
若是你在執行完錯誤的命令後馬上發現了問題,而且沒有commit,能夠經過如下命令將HEAD指向新建的本地分支localBranch,這時就解決了detached狀態,而且此時的localBranch已經和origin/branch關聯了,能夠放心修改/提交代碼
git checkout -b localBranch
若是已經checkout後,commit了大量代碼,就要當心了。
咱們解決的思路是:
經過reflog肯定最後一次提交的操做id,如1ebf663
git reflog
從這個操做新建一個緩存分支temp
git branch temp 1ebf663
拉取但願同步的遠程分支,執行該命令後會自動切換到targetBranch上
git checkout --track origin/targetBranch
將緩存分支合併到但願同步的分支上
git merge temp
接下來就能夠放心提交了~
--END
蔣鑫 Git權威指南學習筆記,這是一本手冊性的書籍
☯ git config <section>.<key>能夠讀取配置配置文件中的配置信息
☯git config <section>.<key> <value>能夠設置配置文件,有一下三種級別的配置
git config --global core.eidtor vim //將git默認的編輯器配置爲vim
git config --global push.default simple//將push.default設置爲simple模式。關於push.default:
當使用git push推送而不加任何參數時,push.default參數就起做用了。能夠經過man git config 命令查看官方的文檔中關於push.default的說明。push.default一些值的說明:
· nothing - do not push anything (error out) unless a refspec is explicitly given. This is primarily meant for people who want to avoid mistakes by always being explicit.
· current - push the current branch to update a branch with the same name on the receiving end. Works in both central and non-central workflows.【將當前分支推送到接收端同名的分支】
· upstream - push the current branch back to the branch whose changes are usually integrated into the current branch (which is called @{upstream}). This mode only makes sense if you are pushing to the same repository you would normally pull from (i.e. central workflow). [將當前分支推送到上游分支。這個參數只適用於 拉取和推送的遠程服務器是同一個的狀況 (即所謂的中心化工做流)。]
· simple - in centralized workflow, work like upstream with an added safety to refuse to push if the upstream branch’s name is different from the local one. When pushing to a remote that is different from the remote you normally pull from, work as current. This is the safest option and is suited for beginners. 【在中心化工做流中, 此模式和current模式相似,可是加了一個安全限制:若是本地分支名和上 遊分支名不同,git將拒絕推送。若是不是中心化工做流(即拉取的遠程服務器和將要推送的遠程服務器不是同一個),這個模式和current模式同樣。】
This mode has become the default in Git 2.0. [這個模式在git2.0版本以後是起默認模式]
· matching - push all branches having the same name on both ends. This makes the repository you are pushing to remember the set of branches that will be pushed out (e.g. if you always push maint and master there and no other branches, the repository you push to will have these two branches, and your local maint and master will be pushed there).【這個模式會將本地與遠程服務器上 全部同名的 分支一併推送過去】
暫存區稱爲stage或index,也叫索引區git diff HEAD表示當前工做區與HEAD(版本庫中的最新提交)的差別
git diff
git diff HEAD
git diff --cached/--staged
git cat-file -t sha1// type
git cat-file -p sha1//content
.git/refs目錄下的結構:
目錄.git/refs是保存引用的命名空間,其中.git/refs/heads目錄下的引用又稱爲分支。對於分支,既能夠使用正規的長格式表示法refs/heads/master,也能夠去掉前面的兩極目錄用master來表示。
git rev-parse [master] //用於顯示指定的引用對應的提交ID。
.git/HEAD---->.git/refs/heads/maser--->commitID---->①目錄樹②父提交
git reset 改變的是.git/refs/master中的指向。可是帶路徑的用法不改變其內容(即master的指向),只是用來將指定的commit中的文件替換掉 暫存區 的文件。不加commit默認爲HEAD
git checkout 改變的是.git/HEAD中的指向。可是帶路徑的用法不改變其內容,只是用來將指定的commit中的文件替換掉 暫存區和工做區中的文件,不加commit則是將暫存區中的文件替換掉工做區中的文件。[注意:不是徹底覆蓋,只是覆蓋commit中已有的文件!!!這句話很關鍵]
使用reflog挽救錯誤的重置,.git/logs目錄下的日誌文件記錄了分支或HEAD的變動。
git reflog show [master] -n //顯示.git/logs/refs/heads/master下的日誌文件(格式通過整理了)。若是不加maser默認爲HEAD,即顯示.git/logs/HEAD中的日誌文件。show關鍵字貌似可用可不用..
git stash
git stash實際上用到了git reset --hard HEAD命令。
.git/refs/stash //git stash會將進度保存在引用refs/stash文件所指向的提交中。屢次的進度保存實際上至關於引用refs/stash文件一次又一次的變化,而refs/stash引用的變化由reflog(即.git/logs/refs/stash文件)所記錄下來。
git reflog show refs/stash //顯示各次stash的變化日誌
git log refs/stash //提交歷史中包含了stash所作的提交。
改變歷史:挑選操做,變基操做,交互式變基操做
①挑選操做:git cherry-pick
其含義是從衆多的提交中挑選出一個提交應用在當前的工做分支中。該命令須要提供一個提交ID做爲參數,操做過程至關於將該提交導出爲補丁文件,而後在當前HEAD上重放,造成不管內容仍是提交說明都一致的提交。
②變基操做
對提交執行變基操做,便可以實現將指定範圍的提交「嫁接」到另一個提交之上。
③交互式變基操做
[當你以爲某項技術很難理解時,換本書看!]
https://git-scm.com/book/zh/v2# 學習筆記
*格式:第一部分:1,2,3,4, 第二部分,1, 2,3,4
第一部分:Git基礎知識
0,
git 分爲3個區域:①工做區;②暫存區; ③倉庫區。其中暫存區和倉庫區都是在.git目錄中。
Git 保存的不是文件的變化或者差別,而是一系列不一樣時刻的文件快照(即當時的全部內容)。
1:clone
$ git clone https://github.com/libgit2/libgit2這會在當前目錄下建立一個名爲 「libgit2」 的目錄,並在這個目錄下初始化一個
.git
文件夾,從遠程倉庫拉取下全部數據放入.git
文件夾,而後從中讀取最新版本的文件的拷貝。 若是你進入到這個新建的libgit2
文件夾,你會發現全部的項目文件已經在裏面了,準備就緒等待後續的開發和使用。 若是你想在克隆遠程倉庫的時候,自定義本地倉庫的名字,你能夠使用以下命令:$ git clone https://github.com/libgit2/libgit2 mylibgit
2:添加到暫存區
git add
命令。 這是個多功能命令:能夠用它開始跟蹤新文件,或者把已跟蹤的文件放到暫存區,還能用於合併時把有衝突的文件標記爲已解決狀態等。 將這個命令理解爲「添加內容到下一次提交中」而不是「將一個文件添加到項目中」要更加合適。
git add -A
stages Allgit add .
stages new and modified, without deletedgit add -u
stages modified and deleted, without new
3:忽略文件列表
文件
.gitignore
的格式規範以下:
- 全部空行或者以
#
開頭的行都會被 Git 忽略。
能夠使用標準的 glob 模式匹配。
匹配模式能夠以(
/
)開頭防止遞歸。匹配模式能夠以(
/
)結尾指定目錄。要忽略指定模式之外的文件或目錄,能夠在模式前加上驚歎號(
!
)取反。所謂的 glob 模式是指 shell 所使用的簡化了的正則表達式。 星號(
*
)匹配零個或多個任意字符;[abc]
匹配任何一個列在方括號中的字符(這個例子要麼匹配一個 a,要麼匹配一個 b,要麼匹配一個 c);問號(?
)只匹配一個任意字符;若是在方括號中使用短劃線分隔兩個字符,表示全部在這兩個字符範圍內的均可以匹配(好比[0-9]
表示匹配全部 0 到 9 的數字)。 使用兩個星號(*
) 表示匹配任意中間目錄,好比`a/**/z` 能夠匹配a/z
,a/b/z
或 `a/b/c/z`等。咱們再看一個 .gitignore 文件的例子:
# no .a files *.a # but do track lib.a, even though you're ignoring .a files above !lib.a # only ignore the TODO file in the current directory, not subdir/TODO /TODO # ignore all files in the build/ directory build/ # ignore doc/notes.txt, but not doc/server/arch.txt doc/*.txt # ignore all .pdf files in the doc/ directory doc/**/*.pdf
4:差別
git diff [filelist]命令不加參數比較工做區和暫存區之間的差別(以暫存區爲基準,由於工做區是更加新的內容)
git diff --staged [filelist]比較暫存區和倉庫區之間的差別(以倉庫區爲基準,由於暫存區是更加新的內容).--cached和--staged是同義詞。
5:提交
※每一次運行提交操做,都是對你項目做一次快照(快照都是在倉庫裏都),之後能夠回到這個狀態,或者進行比較。
※git commit -a : -a選項能夠自動把已經跟蹤(跟蹤的意思便是此文件已經被暫存過)過的文件暫存起來並提交,跳過了暫存命令。可是注意,這個文件必須已經被跟蹤過,不然沒法直接提交到倉庫。
6:移除文件
※ git rm [file] 將file從暫存區以及工做區刪除。如此此文件之後便不會再被git管理。使用git rm時注意,若是file有數據還沒有被提交到git倉庫中,那麼git rm會出錯。必須使用-f參數強制刪除。這是一種保護機制,用於防止誤刪尚未添加到快照(倉庫)中的數據,而這樣的數據git是沒法恢復的。
※另一種狀況是,咱們想把文件從 Git 倉庫中刪除(亦即從暫存區域移除),但仍然但願保留在當前工做目錄中。 換句話說,你想讓文件保留在磁盤,可是並不想讓 Git 繼續跟蹤。 當你忘記添加
.gitignore
文件,不當心把一個很大的日誌文件或一堆.a
這樣的編譯生成文件添加到暫存區時,這一作法尤爲有用。 爲達到這一目的,使用--cached
選項:$ git rm --cached README
git rm
命令後面能夠列出文件或者目錄的名字,也能夠使用glob
模式。 比方說:$ git rm log/\*.log注意到星號
*
以前的反斜槓\
, 由於 Git 有它本身的文件模式擴展匹配方式,因此咱們不用 shell 來幫忙展開(即讓*保持本身的含義,git會識別*而後匹配)。 此命令刪除log/
目錄下擴展名爲.log
的全部文件。 相似的好比:$ git rm \*~該命令爲刪除以
~
結尾的全部文件
7, 移動文件
$ git mv file_from file_to
它會恰如預期般正常工做。 實際上,即使此時查看狀態信息,也會明白無誤地看到關於重命名操做的說明:
$ git mv README.md README
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)renamed: README.md -> README
其實,運行 git mv 就至關於運行了下面三條命令:
$ mv README.md README
$ git rm README.md
$ git add README
如此分開操做,Git 也會意識到這是一次更名,因此無論何種方式結果都同樣。 二者惟一的區別是,mv 是一條命令而另外一種方式須要三條命令,直接用 git mv 輕便得多。 不過有時候用其餘工具批處理更名的話,要記得在提交前刪除老的文件名,再添加新的文件名。
8:歷史 git log
※一個經常使用的選項是
-p
,用來顯示每次提交的內容差別。 你也能夠加上-2
來僅顯示最近兩次提交.※每次提交的簡略的統計信息,你能夠使用
--stat
選項.※另一個經常使用的選項是
--pretty
。 這個選項能夠指定使用不一樣於默認格式的方式展現提交歷史。 這個選項有一些內建的子選項供你使用。 好比用oneline
將每一個提交放在一行顯示,查看的提交數很大時很是有用。 另外還有short
,full
和fuller
能夠用,展現的信息或多或少有些不一樣。其中最有意思的子選項是format,能夠定製要顯示的記錄格式。如:git log --pretty=format:"%h - %an, %ar : %s"經常使用的選項以下:
Table 1. git log --pretty=format
經常使用的選項選項 說明
%H
提交對象(commit)的完整哈希字串
%h
提交對象的簡短哈希字串
%T
樹對象(tree)的完整哈希字串
%t
樹對象的簡短哈希字串
%P
父對象(parent)的完整哈希字串
%p
父對象的簡短哈希字串
%an
做者(author)的名字
%ae
做者的電子郵件地址
%ad
做者修訂日期(能夠用 --date= 選項定製格式)
%ar
做者修訂日期,按多久之前的方式顯示
%cn
提交者(committer)的名字
%ce
提交者的電子郵件地址
%cd
提交日期
%cr
提交日期,按多久之前的方式顯示
%s
提交說明
做者 和 提交者 之間究竟有何差異, 其實做者指的是實際做出修改的人,提交者指的是最後將此工做成果提交到倉庫的人。 因此,當你爲某個項目發佈補丁,而後某個核心成員將你的補丁併入項目時,你就是做者,而那個核心成員就是提交者。 咱們會在 分佈式 Git 再詳細介紹二者之間的細微差異
※當 oneline 或 format 與另外一個
log
選項--graph
結合使用時尤爲有用。 這個選項添加了一些ASCII字符串來形象地展現你的分支、合併歷史。如下表是git log 的全部可用參數及其說明
Table 2. git log
的經常使用選項選項 說明
-p
按補丁格式顯示每一個更新之間的差別。
--stat
顯示每次更新的文件修改統計信息。
--shortstat
只顯示 --stat 中最後的行數修改添加移除統計。
--name-only
僅在提交信息後顯示已修改的文件清單。
--name-status
顯示新增、修改、刪除的文件清單。
--abbrev-commit
僅顯示 SHA-1 的前幾個字符,而非全部的 40 個字符。
--relative-date
使用較短的相對時間顯示(好比,「2 weeks ago」)。
--graph
顯示 ASCII 圖形表示的分支合併歷史。
--pretty
使用其餘格式顯示歷史提交信息。可用的選項包括 oneline,short,full,fuller 和 format(後跟指定格式)。
※限制輸出長度
除了定製輸出格式的選項以外,git log 還有許多很是實用的限制輸出長度的選項,也就是隻輸出部分提交信息。 以前你已經看到過 -2 了,它只顯示最近的兩條提交, 實際上,這是 -<n> 選項的寫法,其中的 n 能夠是任何整數,表示僅顯示最近的若干條提交。 不過實踐中咱們是不太用這個選項的,Git 在輸出全部提交時會自動調用分頁程序,因此你一次只會看到一頁的內容。
另外還有按照時間做限制的選項,好比 --since 和 --until 也頗有用。 例如,下面的命令列出全部最近兩週內的提交:
$ git log --since=2.weeks
這個命令能夠在多種格式下工做,好比說具體的某一天 "2008-01-15",或者是相對地多久之前 "2 years 1 day 3 minutes ago"。還能夠給出若干搜索條件,列出符合的提交。 用 --author 選項顯示指定做者的提交,用 --grep 選項搜索提交說明中的關鍵字。 (請注意,若是要獲得同時知足這兩個選項搜索條件的提交,就必須用 --all-match 選項。不然,知足任意一個條件的提交都會被匹配出來)
另外一個很是有用的篩選選項是 -S,能夠列出那些添加或移除了某些字符串的提交。 好比說,你想找出添加或移除了某一個特定函數的引用的提交,你能夠這樣使用:
$ git log -S function_name
最後一個很實用的 git log 選項是路徑(path), 若是隻關心某些文件或者目錄的歷史提交,能夠在 git log 選項的最後指定它們的路徑。 由於是放在最後位置上的選項,因此用兩個短劃線和空格(「-- 」)隔開以前的選項和後面限定的路徑名。如git log -- tmp.txt
Table 3. 限制 git log
輸出的選項選項 說明
-(n)
僅顯示最近的 n 條提交
--since
,--after
僅顯示指定時間以後的提交。
--until
,--before
僅顯示指定時間以前的提交。
--author
僅顯示指定做者相關的提交。
--committer
僅顯示指定提交者相關的提交。
--grep
僅顯示含指定關鍵字的提交
-S
僅顯示添加或移除了某個關鍵字的提交
9, 撤銷操做
9.1 注意,有些撤消操做是不可逆的。 這是在使用 Git 的過程當中,會由於操做失誤而致使以前的工做丟失的少有的幾個地方之一。
9.2, 有時候咱們提交完了才發現漏掉了幾個文件沒有添加,或者提交信息寫錯了。 此時,能夠運行帶有 --amend 選項的提交命令嘗試從新提交:
$ git commit --amend
git commit --amend命令能夠將暫存區中的文件提交到倉庫替換掉倉庫中最近一次的版本。①若是自上次提交以來你還未作任何修改(例如,在上次提交後立刻執行了此命令),那麼快照會保持不變,而你所修改的只是提交信息。文本編輯器啓動後,能夠看到以前的提交信息。 編輯後保存會覆蓋原來的提交信息。
②你提交後發現忘記了暫存某些須要的修改,能夠像下面這樣操做:
$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend
最終你只會有一個提交 - 第二次提交將代替第一次提交的結果。9.3, 取消暫存區中的文件
git reset HEAD [file] //此命令將file文件從暫存區中刪除,變爲未暫存的狀態
note: 雖然在調用時加上
--hard
選項能夠令git reset
成爲一個危險的命令(譯註:可能致使工做目錄中全部當前進度丟失!),但本例中工做目錄內的文件並不會被修改。 不加選項地調用git reset
並不危險 — 它只會修改暫存區域。9.4, 撤銷對工做區文件的修改
git checkout -- [file] //此命令將file文件撤銷到上一次提交到倉庫中的狀態。
note: 這是一個危險的命令。 你對那個文件作的任何修改都會消失 - 你只是拷貝了另外一個文件來覆蓋它。 除非你確實清楚不想要那個文件了,不然不要使用這個命令。
10, 遠程倉庫的使用
// 場景: 將本地倉庫關聯GitHub自建的某個倉庫並推送本地代碼
git remote add origin githubUrl
git pull origin master --allow-unrelated-histories
git push origin master (git push -u origin master)
--------------------------------
git remote //查看每個遠程服務器(或者說遠程倉庫)的簡寫。若是說是克隆的倉庫,至少有一個origin,這是git給克隆倉庫服務器的默認名字。
git remote -v //查看簡寫及其對應的URL
git remote add <shortname> <url> //添加一個新的遠程Git倉庫,同時爲其指定一個簡寫別名。
git remote rm [remote-repository name] // 移除一個遠程倉庫。
git remote show [remote-name] //check more info of a remote repository
git remote rename [oldname] [newname] // rename a remote repository, 這個命令一樣會修改你的遠程分支名稱。如:oldname/master ---> newname/master
git remote set-url origin 'http://gs.mizss.com/hanfeng/eiduo.git' //從新設置遠程倉庫origin的地址,好比當遠程項目更名字了就須要從新設置一下。
git ls-remote [remote] //顯式獲取遠程引用的完整列表, remote指遠程服務器(倉庫)名
git remote show [remote] // 獲取遠程分支的更多信息
origin/master 是本地的一個分支,它指向服務器倉庫origin的master分支
git clone -o [clone_name] //克隆的遠程分支名默認爲clone_name / master
git push [remote] [branch]
git push [remote] [local_branch]:[remote_branch] 【本地和遠程分支名稱能夠不一樣.若是遠程尚未相應分支,則會自動建立名稱爲remote_branch的分支】
git push -u [remote] [local_branch]:[remote_branch]
-u
標記;這是--set-upstream
的簡寫,設置上游分支(上游分支是指以本地的origin/master表明的遠程的master分支, origin/master是本地的遠程分支, 可能與遠程倉庫不同,經過git pull origin master 與遠程倉庫保持同步。),即將remote_branch與本地的local_branch關聯起來,只須要在第一次推送時使用。該標記會爲以後輕鬆地推送與拉取配置分支。【使用場景:只有本地有分支,遠程沒有對應分支時,注意冒號先後不能有空格】git fetch origin //
git pull // 至關於git fetch 和git merge兩個命令。當遠程倉庫和本地倉庫是兩個獨立的倉庫時,第一次 git pull 會報錯:fatal: refusing to merge unrelated histories,使用下面命令便可。git pull origin master --allow-unrelated-histories
git checkout -b [new_branch] //基於當前分支建立一個新的分支並當即切換到新分支上
git checkout -b [new_branch] [existing_branch] // 基於existing_branch分支建立一個新的分支並當即切換到新分支上。
git checkout -b [new_branch] [commit_id] //基於當前分支的某次提交建立一個新的分支並當即切換到新的分支上。
git checkout -b [local_branch] [remote/branch]//基於遠程分支在本地建立一個新的分支並當即切換到新的分支上去。//這個是拉取本地不存在的遠程分支的方法!!若是本地尚未遠程分支,使用 git fetch 將新的遠程分支拉取到本地,而後再執行上述命令。
git branch -u [remote/branch] //將當前分支設置爲跟蹤[remote/branch]的分支
git branch -vv (注意是兩個v不是w) //將全部的本地分支列出來而且包含更多的信息。
git push orgin --delete [branch] //刪除遠程分支。這個命令作的只是從服務器上移除這個指針。 Git 服務器一般會保留數據一段時間直到垃圾回收運行,因此若是不當心刪除掉了,一般是很容易恢復的
git merge的徹底使用手冊:https://www.jianshu.com/p/58a166f24c81
git fetch [remote-name] //從遠程倉庫中拉取數據
這個命令會訪問遠程倉庫,從中拉取全部你尚未的數據。 執行完成後,你將會擁有那個遠程倉庫中全部分支的引用,能夠隨時合併或查看。
若是你使用 clone 命令克隆了一個倉庫,命令會自動將其添加爲遠程倉庫並默認以 「origin」 爲簡寫。 因此,git fetch origin 會抓取克隆(或上一次抓取)後新推送的全部工做。 必須注意 git fetch 命令會將數據拉取到你的本地倉庫 - 它並不會自動合併或修改你當前的工做。 當準備好時你必須手動將其合併入你的工做。
若是你有一個分支設置爲跟蹤一個遠程分支(閱讀下一節與 Git 分支 瞭解更多信息),能夠使用 git pull 命令來自動的抓取而後合併遠程分支到當前分支。 這對你來講多是一個更簡單或更舒服的工做流程;默認狀況下,git clone 命令會自動設置本地 master 分支跟蹤克隆的遠程倉庫的 master 分支(或無論是什麼名字的默認分支)。 運行 git pull 一般會從最初克隆的服務器上抓取數據並自動嘗試合併到當前所在的分支。
git push [remote-name] [branch-name]//推送到遠程倉庫
當你想分享你的項目時,必須將其推送到上游。 這個命令很簡單:git push [remote-name] [branch-name]。 當你想要將 master 分支推送到 origin 服務器時(再次說明,克隆時一般會自動幫你設置好那兩個名字),那麼運行這個命令就能夠將你所作的備份到服務器:$ git push origin master
只有當你有所克隆服務器的寫入權限,而且以前沒有人推送過期,這條命令才能生效。 當你和其餘人在同一時間克隆,他們先推送到上游而後你再推送到上游,你的推送就會毫無疑問地被拒絕。 你必須先將他們的工做拉取下來並將其合併進你的工做後才能推送。 閱讀 Git 分支 瞭解如何推送到遠程倉庫服務器的詳細信息。
11, 打標籤
1, Git能夠給歷史中的某一個提交打上標籤,以示重要,好比標記發佈節點(v1.0等等)。
2, 列出標籤
git tag
git tag -l 'v1.0*' //只列出v1.0相關的標籤。
3,建立 標籤
3.0, 從遠程倉庫拉取代碼時,git pull並不會將標籤拉下來,git fetch 則會將標籤拉下來。
Git 使用兩種主要類型的標籤:輕量標籤(lightweight)與附註標籤(annotated)。
一個輕量標籤很像一個不會改變的分支 - 它只是一個特定提交的引用。
然而,附註標籤是存儲在 Git 數據庫中的一個完整對象。 它們是能夠被校驗的;其中包含打標籤者的名字、電子郵件地址、日期時間;還有一個標籤信息;而且能夠使用 GNU Privacy Guard (GPG)簽名與驗證(-s參數)。 一般建議建立附註標籤,這樣你能夠擁有以上全部信息;可是若是你只是想用一個臨時的標籤,或者由於某些緣由不想要保存那些信息,輕量標籤也是可用的。
3,1, 附註標籤
在 Git 中建立一個附註標籤是很簡單的。 最簡單的方式是當你在運行
tag
命令時指定-a
選項:
$ git tag -a v1.4 -m 'my version 1.4'
經過使用
git show
<tag> 命令能夠看到標籤信息與對應的提交信息。輸出顯示了打標籤者的信息、打標籤的日期時間、附註信息,而後顯示具體的提交信息。3.2, 輕量標籤
另外一種給提交打標籤的方式是使用輕量標籤。 輕量標籤本質上是將提交校驗和存儲到一個文件中 - 沒有保存任何其餘信息。 建立輕量標籤,不須要使用
-a
、-s
或-m
選項,只須要提供標籤名字:$ git tag v1.4
這時,若是在標籤上運行
git show <tag>
,你不會看到額外的標籤信息。 命令只會顯示出提交信息。3.3, 爲過去的某次歷史提交打標籤
要在那個提交上打標籤,你須要在命令的末尾指定提交的校驗和(或部分校驗和):
$ git tag -a v1.2 8fcdb32
3.4, 共享標籤
※ 默認狀況下,git push 命令並不會傳送標籤到遠程倉庫服務器上。 在建立完標籤後你必須顯式地推送標籤到共享服務器上。 這個過程就像共享遠程分支同樣 - 你能夠運行 git push origin [tagname] / git push origin <branchName> [tagname]。
※ 若是想要一次性推送不少標籤,也能夠使用帶有
--tags
選項的git push
命令 git push origin --tags。 這將會把全部不在遠程倉庫服務器上的標籤所有傳送到那裏。如今,當其餘人從倉庫中克隆或拉取,他們也能獲得你的那些標籤。
3.5,刪除標籤
※刪除本地標籤: git tag -d v1.0.0 (或 git tag --delete v1.0.0)
※刪除遠程倉庫標籤:git push origin <branchName> -d (--delete) v1.0.0
4,檢出標籤
在 Git 中你並不能真的檢出一個標籤,由於它們並不能像分支同樣來回移動。 若是你想要工做目錄與倉庫中特定的標籤版本徹底同樣,能夠使用 git checkout -b [branchname] [tagname] 在特定的標籤上建立一個新分支:
$ git checkout -b version2 v2.0.0
Switched to a new branch 'version2'
固然,若是在這以後又進行了一次提交,version2 分支會由於改動向前移動了,那麼 version2 分支就會和 v2.0.0 標籤稍微有些不一樣,這時就應該小心了。
12, Git別名
git config --global alias.co checkout
能夠看出,Git 只是簡單地將別名替換爲對應的命令。 然而,你可能想要執行外部命令,而不是一個 Git 子命令。 若是是那樣的話,能夠在命令前面加入 ! 符號。 若是你本身要寫一些與 Git 倉庫協做的工具的話,那會頗有用。 咱們如今演示將 git visual 定義爲 gitk 的別名:
$ git config --global alias.visual '!gitk'
第二部分:Git 的殺手級特性:分支模型。
1, 分支簡介(重要,對於理解頗有幫助)
Git保存的不是文件的變化或者差別,而是一系列不一樣時刻的文件快照。
在進行暫存操做時,git會爲每個文件計算 校驗和(即指紋) ,而後會把當前版本的文件快照保存到Git倉庫中(Git使用blob對象來 保存它們),最終將 校驗和 加入到暫存區域等待提交;
在進行提交操做時,Git會先計算項目根目錄及其每個子目錄的 校驗和, 而後在Git倉庫中將這個 校驗和 保存爲 樹對象。隨後,Git便會建立一個提交對象,它包含了①做者的姓名,郵箱,提交時輸入的信息②指向 前面敘述過的 樹對象 的指針。如此,Git就能夠在須要的時候重現這次保存的快照③指向 它的父對象的指針(第一次提交時沒有)。
形象說明一下,如今假設有一個工做目錄,裏面包含了3個文件,而後執行以下操做:
$ git add README test.rb LICENSE
$ git commit -m 'The initial commit of my project'如今Git倉庫裏有五個對象:三個blob對象(保存着文件快照)、一個樹對象(記錄着目錄結構和blob對象索引)以及一個提交對象(包含着指向前述樹對象的指針和全部提交信息)。以下圖所示:
作些修改後再次提交,那麼此次產生的提交對象會包含一個指向上次提交對象(父對象)的指針,以下圖所示:
Git的分支,其實本質上僅僅是指向提交對象的可變指針。Git默認分支名字是master。每次提交操做中,分支指針都會自動向前移動。以下圖所示:
2, 分支建立
git branch //查看分支
git branch -a//查看全部分支
git branch new_branch //基於當前分支的最新提交建立一個新的分支,新分支名稱叫newBranch
git branch new_branch existing_branch //不管如今在哪一個分支上,此命令會基於existing_branch的最新提交建立一個新分支。
git branch new_branch [commit_id] //不管如今在哪一個分支上,此命令會基於某個提交(能夠是當前分支的某個提交,也能夠是其餘任意一個分支上的某個提交ID)建立一個新分支。
Git 是怎麼建立新分支的呢? 很簡單,它只是爲你建立了一個能夠移動的新的指針。 好比,建立一個 testing 分支, 你須要使用 git branch 命令:
$ git branch testing
這會在當前所在的提交對象上建立一個指針。以下圖所示:
那麼,Git 又是怎麼知道當前在哪個分支上呢? 也很簡單,它有一個名爲
HEAD
的特殊指針。 請注意它和許多其它版本控制系統(如 Subversion 或 CVS)裏的HEAD
概念徹底不一樣。 在 Git 中,它是一個指針,指向當前所在的本地分支(譯註:將HEAD
想象爲當前分支的別名)。 在本例中,你仍然在master
分支上。 由於git branch
命令僅僅 建立 一個新分支,並不會自動切換到新分支中去。以下圖所示:
你能夠簡單地使用
git log
命令查看各個分支當前所指的對象。 提供這一功能的參數是--decorate
。
3, 分支切換
要切換到一個已存在的分支,你須要使用 git checkout 命令。 咱們如今切換到新建立的 testing 分支去:
$ git checkout testing
這樣 HEAD 就指向 testing 分支了。以下圖所示:
這麼作的好處是什麼呢?如今不妨作些改動再提交一次,以下圖所示:
如圖所示,你的
testing
分支向前移動了,可是master
分支卻沒有,它仍然指向運行git checkout
時所指的對象。 這就有意思了,如今咱們切換回master
分支看看:
這條命令作了兩件事。 一是使 HEAD 指回
master
分支,二是將工做目錄恢復成master
分支所指向的快照內容。 也就是說,你如今作修改的話,項目將始於一個較舊的版本。 本質上來說,這就是忽略testing
分支所作的修改,以便於向另外一個方向進行開發。
Note 分支切換會改變你工做目錄中的文件在切換分支時,必定要注意你工做目錄裏的文件會被改變。 若是是切換到一個較舊的分支,你的工做目錄會恢復到該分支最後一次提交時的樣子。 若是 Git 不能幹淨利落地完成這個任務,它將禁止切換分支。
咱們不妨再稍微作些修改並提交。
如今,這個項目的提交歷史已經產生了分叉(參見 項目分叉歷史)。 由於剛纔你建立了一個新分支,並切換過去進行了一些工做,隨後又切換回 master 分支進行了另一些工做。 上述兩次改動針對的是不一樣分支:你能夠在不一樣分支間不斷地來回切換和工做,並在時機成熟時將它們合併起來。 而全部這些工做,你須要的命令只有 branch、checkout 和 commit。
你能夠簡單地使用
git log
命令查看分叉歷史。 運行git log --oneline --decorate --graph --all
,它會輸出你的提交歷史、各個分支的指向以及項目的分支分叉狀況。因爲 Git 的分支實質上僅是包含所指提交對象校驗和(長度爲 40 的 SHA-1 值字符串)的文件,因此它的建立和銷燬都異常高效。 建立一個新分支就至關於往一個文件中寫入 41 個字節(40 個字符和 1 個換行符),如此的簡單能不快嗎?
這與過去大多數版本控制系統造成了鮮明的對比,它們在建立分支時,將全部的項目文件都複製一遍,並保存到一個特定的目錄。 完成這樣繁瑣的過程一般須要好幾秒鐘,有時甚至須要好幾分鐘。所需時間的長短,徹底取決於項目的規模。而在 Git 中,任何規模的項目都能在瞬間建立新分支。 同時,因爲每次提交都會記錄父對象,因此尋找恰當的合併基礎(譯註:即共同祖先)也是一樣的簡單和高效。 這些高效的特性使得 Git 鼓勵開發人員頻繁地建立和使用分支。
4, 分支的新建與合併
讓咱們來看一個簡單的分支新建與分支合併的例子,實際工做中你可能會用到相似的工做流。 你將經歷以下步驟:
- 開發某個網站。
- 爲實現某個新的需求,建立一個分支。
- 在這個分支上開展工做。
正在此時,你忽然接到一個電話說有個很嚴重的問題須要緊急修補。 你將按照以下方式來處理:
- 切換到你的線上分支(production branch)。
- 爲這個緊急任務新建一個分支,並在其中修復它。
- 在測試經過以後,切換回線上分支,而後合併這個修補分支,最後將改動推送到線上分支。
- 切換回你最初工做的分支上,繼續工做
新建分支
首先,咱們假設你正在你的項目上工做,而且已經有一些提交。
Figure 18. 一個簡單提交歷史如今,你已經決定要解決你的公司使用的問題追蹤系統中的 #53 問題。 想要新建一個分支並同時切換到那個分支上,你能夠運行一個帶有
-b
參數的git checkout
命令:$ git checkout -b iss53 Switched to a new branch "iss53"它是下面兩條命令的簡寫:
$ git branch iss53 $ git checkout iss53
Figure 19. 建立一個新分支指針你繼續在 #53 問題上工做,而且作了一些提交。 在此過程當中,
iss53
分支在不斷的向前推動,由於你已經檢出到該分支(也就是說,你的HEAD
指針指向了iss53
分支)$ vim index.html $ git commit -a -m 'added a new footer [issue 53]'
Figure 20. iss53 分支隨着工做的進展向前推動如今你接到那個電話,有個緊急問題等待你來解決。 有了 Git 的幫助,你沒必要把這個緊急問題和
iss53
的修改混在一塊兒,你也不須要花大力氣來還原關於 53# 問題的修改,而後再添加關於這個緊急問題的修改,最後將這個修改提交到線上分支。 你所要作的僅僅是切換回master
分支。可是,在你這麼作以前,要留意你的工做目錄和暫存區裏那些尚未被提交的修改,它可能會和你即將檢出的分支產生衝突從而阻止 Git 切換到該分支。 最好的方法是,在你切換分支以前,保持好一個乾淨的狀態。 有一些方法能夠繞過這個問題(即,保存進度(stashing) 和 修補提交(commit amending)),咱們會在 儲藏與清理 中看到關於這兩個命令的介紹。 如今,咱們假設你已經把你的修改所有提交了,這時你能夠切換回
master
分支了:$ git checkout master Switched to branch 'master'這個時候,你的工做目錄和你在開始 #53 問題以前如出一轍,如今你能夠專心修復緊急問題了。 請牢記:當你切換分支的時候,Git 會重置你的工做目錄,使其看起來像回到了你在那個分支上最後一次提交的樣子。 Git 會自動添加、刪除、修改文件以確保此時你的工做目錄和這個分支最後一次提交時的樣子如出一轍。
接下來,你要修復這個緊急問題。 讓咱們創建一個針對該緊急問題的分支(hotfix branch),在該分支上工做直到問題解決:
$ git checkout -b hotfix Switched to a new branch 'hotfix' $ vim index.html $ git commit -a -m 'fixed the broken email address' [hotfix 1fb7853] fixed the broken email address 1 file changed, 2 insertions(+)
Figure 21. 基於master
分支的緊急問題分支hotfix branch
你能夠運行你的測試,確保你的修改是正確的,而後將其合併回你的
master
分支來部署到線上。 你能夠使用git merge
命令來達到上述目的:$ git checkout master $ git merge hotfix Updating f42c576..3a0874c Fast-forward index.html | 2 ++ 1 file changed, 2 insertions(+)在合併的時候,你應該注意到了"快進(fast-forward)"這個詞。 因爲當前
master
分支所指向的提交是你當前提交(有關 hotfix 的提交)的直接上游,因此 Git 只是簡單的將指針向前移動。 換句話說,當你試圖合併兩個分支時,若是順着一個分支走下去可以到達另外一個分支,那麼 Git 在合併二者的時候,只會簡單的將指針向前推動(指針右移),由於這種狀況下的合併操做沒有須要解決的分歧——這就叫作 「快進(fast-forward)」。如今,最新的修改已經在
master
分支所指向的提交快照中,你能夠着手發佈該修復了。
Figure 22.master
被快進到hotfix
關於這個緊急問題的解決方案發布以後,你準備回到被打斷以前時的工做中。 然而,你應該先刪除
hotfix
分支,由於你已經再也不須要它了 ——master
分支已經指向了同一個位置。 你能夠使用帶-d
選項的git branch
命令來刪除分支:$ git branch -d hotfix Deleted branch hotfix (3a0874c).如今你能夠切換回你正在工做的分支繼續你的工做,也就是針對 #53 問題的那個分支(iss53 分支)。
$ git checkout iss53 Switched to branch "iss53" $ vim index.html $ git commit -a -m 'finished the new footer [issue 53]' [iss53 ad82d7a] finished the new footer [issue 53] 1 file changed, 1 insertion(+)
Figure 23. 繼續在iss53
分支上的工做你在
hotfix
分支上所作的工做並無包含到iss53
分支中。 若是你須要拉取hotfix
所作的修改,你能夠使用git merge master
命令將master
分支合併入iss53
分支,或者你也能夠等到iss53
分支完成其使命,再將其合併回master
分支。分支的合併
假設你已經修正了 #53 問題,而且打算將你的工做合併入
master
分支。 爲此,你須要合併iss53
分支到master
分支,這和以前你合併hotfix
分支所作的工做差很少。 你只須要檢出到你想合併入的分支,而後運行git merge
命令:$ git checkout master Switched to branch 'master' $ git merge iss53 Merge made by the 'recursive' strategy. index.html | 1 + 1 file changed, 1 insertion(+)這和你以前合併
hotfix
分支的時候看起來有一點不同。 在這種狀況下,你的開發歷史從一個更早的地方開始分叉開來(diverged)。 由於,master
分支所在提交併非iss53
分支所在提交的直接祖先,Git 不得不作一些額外的工做。 出現這種狀況的時候,Git 會使用兩個分支的末端所指的快照(C4
和C5
)以及這兩個分支的工做祖先(C2
),作一個簡單的三方合併。
Figure 24. 一次典型合併中所用到的三個快照和以前將分支指針向前推動所不一樣的是,Git 將這次三方合併的結果作了一個新的快照而且自動建立一個新的提交指向它。 這個被稱做一次合併提交,它的特別之處在於他有不止一個父提交。
Figure 25. 一個合併提交須要指出的是,Git 會自行決定選取哪個提交做爲最優的共同祖先,並以此做爲合併的基礎;這和更加古老的 CVS 系統或者 Subversion (1.5 版本以前)不一樣,在這些古老的版本管理系統中,用戶須要本身選擇最佳的合併基礎。 Git 的這個優點使其在合併操做上比其餘系統要簡單不少。
既然你的修改已經合併進來了,你已經再也不須要
iss53
分支了。 如今你能夠在任務追蹤系統中關閉此項任務,並刪除這個分支。$ git branch -d iss53
遇到衝突時的分支合併
有時候合併操做不會如此順利。 若是你在兩個不一樣的分支中,對同一個文件的同一個部分進行了不一樣的修改,Git 就無法乾淨的合併它們。 若是你對 #53 問題的修改和有關
hotfix
的修改都涉及到同一個文件的同一處,在合併它們的時候就會產生合併衝突:$ git merge iss53 Auto-merging index.html CONFLICT (content): Merge conflict in index.html Automatic merge failed; fix conflicts and then commit the result.此時 Git 作了合併,可是沒有自動地建立一個新的合併提交。 Git 會暫停下來,等待你去解決合併產生的衝突。 你能夠在合併衝突後的任意時刻使用
git status
命令來查看那些因包含合併衝突而處於未合併(unmerged)狀態的文件:$ git status On branch master You have unmerged paths. (fix conflicts and run "git commit") Unmerged paths: (use "git add <file>..." to mark resolution) both modified: index.html no changes added to commit (use "git add" and/or "git commit -a")任何因包含合併衝突而有待解決的文件,都會以未合併狀態標識出來。 Git 會在有衝突的文件中加入標準的衝突解決標記,這樣你能夠打開這些包含衝突的文件而後手動解決衝突。 出現衝突的文件會包含一些特殊區段,看起來像下面這個樣子:
<<<<<<< HEAD:index.html <div id="footer">contact : email.support@github.com</div> ======= <div id="footer"> please contact us at support@github.com </div> >>>>>>> iss53:index.html這表示
HEAD
所指示的版本(也就是你的master
分支所在的位置,由於你在運行 merge 命令的時候已經檢出到了這個分支)在這個區段的上半部分(=======
的上半部分),而iss53
分支所指示的版本在=======
的下半部分。 爲了解決衝突,你必須選擇使用由=======
分割的兩部分中的一個,或者你也能夠自行合併這些內容。 例如,你能夠經過把這段內容換成下面的樣子來解決衝突:<div id="footer"> please contact us at email.support@github.com </div>上述的衝突解決方案僅保留了其中一個分支的修改,而且
<<<<<<<
,=======
, 和>>>>>>>
這些行被徹底刪除了。 在你解決了全部文件裏的衝突以後,對每一個文件使用git add
命令來將其標記爲衝突已解決。 一旦暫存這些本來有衝突的文件,Git 就會將它們標記爲衝突已解決。若是你想使用圖形化工具來解決衝突,你能夠運行
git mergetool
,該命令會爲你啓動一個合適的可視化合並工具,並帶領你一步一步解決這些衝突:$ git mergetool This message is displayed because 'merge.tool' is not configured. See 'git mergetool --tool-help' or 'git help config' for more details. 'git mergetool' will now attempt to use one of the following tools: opendiff kdiff3 tkdiff xxdiff meld tortoisemerge gvimdiff diffuse diffmerge ecmerge p4merge araxis bc3 codecompare vimdiff emerge Merging: index.html Normal merge conflict for 'index.html': {local}: modified file {remote}: modified file Hit return to start merge resolution tool (opendiff):若是你想使用除默認工具(在這裏 Git 使用
opendiff
作爲默認的合併工具,由於做者在 Mac 上運行該程序)外的其餘合併工具,你能夠在 「下列工具中(one of the following tools)」 這句後面看到全部支持的合併工具。 而後輸入你喜歡的工具名字就能夠了。
Note若是你須要更加高級的工具來解決複雜的合併衝突,咱們會在 高級合併 介紹更多關於分支合併的內容。
等你退出合併工具以後,Git 會詢問剛纔的合併是否成功。 若是你回答是,Git 會暫存那些文件以代表衝突已解決: 你能夠再次運行
git status
來確認全部的合併衝突都已被解決:$ git status On branch master All conflicts fixed but you are still merging. (use "git commit" to conclude merge) Changes to be committed: modified: index.html若是你對結果感到滿意,而且肯定以前有衝突的的文件都已經暫存了,這時你能夠輸入
git commit
來完成合並提交。 默認狀況下提交信息看起來像下面這個樣子:Merge branch 'iss53' Conflicts: index.html # # It looks like you may be committing a merge. # If this is not correct, please remove the file # .git/MERGE_HEAD # and try again. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # On branch master # All conflicts fixed but you are still merging. # # Changes to be committed: # modified: index.html #
若是你以爲上述的信息不夠充分,不能徹底體現分支合併的過程,你能夠修改上述信息,添加一些細節給將來檢視這個合併的讀者一些幫助,告訴他們你是如何解決合併衝突的,以及理由是什麼。
linux下git 差別對比、衝突解決圖像化工具:beyond-compare【這個也是windows下小烏龜選擇使用的工具】
1, 安裝與破解:https://github.com/jyma1991/Crack-Beyond-Compare-linux
# Crack-Beyond-Compare-linux [crack beyond compare 4 on linux](https://github.com/jyma1991/Crack-Beyond-Compare-linux.git) ## 1.官網下載最新版 Beyond Compare 4 並安裝 * [Beyond Compare 4](http://www.scootersoftware.com/download.php) 安裝命令: ```vim sudo apt install -i bcompare-4.2.3.22587_amd64.deb ``` 若是報錯 「依賴關係問題 - 仍未被配置」 使用以下命令 ```vim sudo apt-get install -f ``` 等分析完以後從新執行安裝命令 ## 2.破解 ```vim cd /usr/lib/beyondcompare/ sudo sed -i "s/keexjEP3t4Mue23hrnuPtY4TdcsqNiJL-5174TsUdLmJSIXKfG2NGPwBL6vnRPddT7tH29qpkneX63DO9ECSPE9rzY1zhThHERg8lHM9IBFT+rVuiY823aQJuqzxCKIE1bcDqM4wgW01FH6oCBP1G4ub01xmb4BGSUG6ZrjxWHJyNLyIlGvOhoY2HAYzEtzYGwxFZn2JZ66o4RONkXjX0DF9EzsdUef3UAS+JQ+fCYReLawdjEe6tXCv88GKaaPKWxCeaUL9PejICQgRQOLGOZtZQkLgAelrOtehxz5ANOOqCaJgy2mJLQVLM5SJ9Dli909c5ybvEhVmIC0dc9dWH+/N9KmiLVlKMU7RJqnE+WXEEPI1SgglmfmLc1yVH7dqBb9ehOoKG9UE+HAE1YvH1XX2XVGeEqYUY-Tsk7YBTz0WpSpoYyPgx6Iki5KLtQ5G-aKP9eysnkuOAkrvHU8bLbGtZteGwJarev03PhfCioJL4OSqsmQGEvDbHFEbNl1qJtdwEriR+VNZts9vNNLk7UGfeNwIiqpxjk4Mn09nmSd8FhM4ifvcaIbNCRoMPGl6KU12iseSe+w+1kFsLhX+OhQM8WXcWV10cGqBzQE9OqOLUcg9n0krrR3KrohstS9smTwEx9olyLYppvC0p5i7dAx2deWvM1ZxKNs0BvcXGukR+/g" BCompare ``` ## 3.此時BCompare文件已被破解,打開軟件會提示「Trial Mode Error!」表示成功,輸入下面TEAM ZWT生成的密鑰便可註冊成功 ```nohighlight --- BEGIN LICENSE KEY --- GXN1eh9FbDiX1ACdd7XKMV7hL7x0ClBJLUJ-zFfKofjaj2yxE53xauIfkqZ8FoLpcZ0Ux6McTyNmODDSvSIHLYhg1QkTxjCeSCk6ARz0ABJcnUmd3dZYJNWFyJun14rmGByRnVPL49QH+Rs0kjRGKCB-cb8IT4Gf0Ue9WMQ1A6t31MO9jmjoYUeoUmbeAQSofvuK8GN1rLRv7WXfUJ0uyvYlGLqzq1ZoJAJDyo0Kdr4ThF-IXcv2cxVyWVW1SaMq8GFosDEGThnY7C-SgNXW30jqAOgiRjKKRX9RuNeDMFqgP2cuf0NMvyMrMScnM1ZyiAaJJtzbxqN5hZOMClUTE+++ --- END LICENSE KEY ----- ``` ## 4.成功後在目錄~/.config/bcompare/下會生成文件BC4Key.txt 以下 ```nohighlight Beyond Compare 4 Licensed to: pwelyn Quantity: 9999 users Serial number: 9571-9981 License type: Pro Edition for Windows/Linux/OS X --- BEGIN LICENSE KEY --- GXN1eh9FbDiX1ACdd7XKMV7hL7x0ClBJLUJ-zFfKofjaj2yxE53xauIfk qZ8FoLpcZ0Ux6McTyNmODDSvSIHLYhg1QkTxjCeSCk6ARz0ABJcnUmd3d ZYJNWFyJun14rmGByRnVPL49QH+Rs0kjRGKCB-cb8IT4Gf0Ue9WMQ1A6t 31MO9jmjoYUeoUmbeAQSofvuK8GN1rLRv7WXfUJ0uyvYlGLqzq1ZoJAJD yo0Kdr4ThF-IXcv2cxVyWVW1SaMq8GFosDEGThnY7C-SgNXW30jqAOgiR jKKRX9RuNeDMFqgP2cuf0NMvyMrMScnM1ZyiAaJJtzbxqN5hZOMClUTE+ --- END LICENSE KEY ----- ``` ## 5.爲全部用戶註冊bcompare 命令 ```vim sudo cp ~/.config/bcompare/BC4Key.txt /etc/ ```
2, 而後配置.gitconfig文件:
[diff] tool = bc3 //設置git difftool的工具是bc3[beyond compare] [merge] tool = bc3 //設置git mergetool的工具是bc3 [difftool] prompt = false //打開前是否提示 [mergetool] prompt = false keepBackup = false //默認狀況下,使用git mergetool合併分支時,總會產生以*.orig爲擴展名的備份文件。將keepBackup設置爲false便可禁止產生備份文件。
5,分支管理
1,經常使用的一些分支管理工具
git branch 命令不僅是能夠建立與刪除分支。 若是不加任何參數運行它,會獲得當前全部分支的一個列表:
$ git branch
iss53
* master
testing
注意 master 分支前的 * 字符:它表明如今檢出的那一個分支(也就是說,當前 HEAD 指針所指向的分支)。 這意味着若是在這時候提交,master 分支將會隨着新的工做向前移動。 若是須要查看每個分支的最後一次提交,能夠運行 git branch -v 命令:$ git branch -v
iss53 93b412c fix javascript issue
* master 7a98805 Merge branch 'iss53'
testing 782fd34 add scott to the author list in the readmes
--merged 與 --no-merged 這兩個有用的選項能夠過濾這個列表中已經合併或還沒有合併到當前分支的分支。 若是要查看哪些分支已經合併到當前分支,能夠運行 git branch --merged:$ git branch --merged
iss53
* master
由於以前已經合併了 iss53 分支,因此如今看到它在列表中。 在這個列表中分支名字前沒有 * 號的分支一般能夠使用 git branch -d 刪除掉;你已經將它們的工做整合到了另外一個分支,因此並不會失去任何東西。查看全部包含未合併工做的分支,能夠運行 git branch --no-merged:
$ git branch --no-merged
testing
這裏顯示了其餘分支。 由於它包含了還未合併的工做,嘗試使用 git branch -d 命令刪除它時會失敗:$ git branch -d testing
error: The branch 'testing' is not fully merged.
If you are sure you want to delete it, run 'git branch -D testing'.
若是真的想要刪除分支並丟掉那些工做,如同幫助信息裏所指出的,能夠使用 -D 選項強制刪除它。另外,git branch -d [brname]是沒法刪除當前正在檢出的分支的。
6,分支開發工做流
在本節,咱們會介紹一些常見的利用分支進行開發的工做流程。而正是因爲分支管理的便捷,才衍生出這些典型的工做模式,你能夠根據項目實際狀況選擇一種用用看。
6.1,長期分支
由於 Git 使用簡單的三方合併,因此就算在一段較長的時間內,反覆把一個分支合併入另外一個分支,也不是什麼難事。 也就是說,在整個項目開發週期的不一樣階段,你能夠同時擁有多個開放的分支;你能夠按期地把某些特性分支合併入其餘分支中。
許多使用 Git 的開發者都喜歡使用這種方式來工做,好比只在
master
分支上保留徹底穩定的代碼——有可能僅僅是已經發布或即將發佈的代碼。 他們還有一些名爲develop
或者next
的平行分支,被用來作後續開發或者測試穩定性——這些分支沒必要保持絕對穩定,可是一旦達到穩定狀態,它們就能夠被合併入master
分支了。 這樣,在確保這些已完成的特性分支(短時間分支,好比以前的iss53
分支)可以經過全部測試,而且不會引入更多 bug 以後,就能夠合併入主幹分支中,等待下一次的發佈。事實上咱們剛纔討論的,是隨着你的提交而不斷右移的指針。 穩定分支的指針老是在提交歷史中落後一大截,而前沿分支的指針每每比較靠前。
Figure 26. 漸進穩定分支的線性圖一般把他們想象成流水線(work silos)可能更好理解一點,那些通過測試考驗的提交會被遴選到更加穩定的流水線上去。
Figure 27. 漸進穩定分支的流水線(「silo」)視圖你能夠用這種方法維護不一樣層次的穩定性。 一些大型項目還有一個
proposed
(建議) 或pu: proposed updates
(建議更新)分支,它可能因包含一些不成熟的內容而不能進入next
或者master
分支。 這麼作的目的是使你的分支具備不一樣級別的穩定性;當它們具備必定程度的穩定性後,再把它們合併入具備更高級別穩定性的分支中。 再次強調一下,使用多個長期分支的方法並不是必要,可是這麼作一般頗有幫助,尤爲是當你在一個很是龐大或者複雜的項目中工做時。6.2,特性分支
特性分支對任何規模的項目都適用。 特性分支是一種短時間分支,它被用來實現單一特性或其相關工做。 也許你歷來沒有在其餘的版本控制系統(
VCS
)上這麼作過,由於在那些版本控制系統中建立和合並分支一般很費勁。 然而,在 Git 中一天以內屢次建立、使用、合併、刪除分支都很常見。你已經在上一節中你建立的
iss53
和hotfix
特性分支中看到過這種用法。 你在上一節用到的特性分支(iss53
和hotfix
分支)中提交了一些更新,而且在它們合併入主幹分支以後,你又刪除了它們。 這項技術能使你快速而且完整地進行上下文切換(context-switch)——由於你的工做被分散到不一樣的流水線中,在不一樣的流水線中每一個分支都僅與其目標特性相關,所以,在作代碼審查之類的工做的時候就能更加容易地看出你作了哪些改動。 你能夠把作出的改動在特性分支中保留幾分鐘、幾天甚至幾個月,等它們成熟以後再合併,而不用在意它們創建的順序或工做進度。考慮這樣一個例子,你在
master
分支上工做到C1
,這時爲了解決一個問題而新建iss91
分支,在iss91
分支上工做到C4
,然而對於那個問題你又有了新的想法,因而你再新建一個iss91v2
分支試圖用另外一種方法解決那個問題,接着你回到master
分支工做了一下子,你又冒出了一個不太肯定的想法,你便在C10
的時候新建一個dumbidea
分支,並在上面作些實驗。 你的提交歷史看起來像下面這個樣子:
Figure 28. 擁有多個特性分支的提交歷史如今,咱們假設兩件事情:你決定使用第二個方案來解決那個問題,即便用在
iss91v2
分支中方案;另外,你將dumbidea
分支拿給你的同事看過以後,結果發現這是個驚人之舉。 這時你能夠拋棄iss91
分支(即丟棄C5
和C6
提交),而後把另外兩個分支合併入主幹分支。 最終你的提交歷史看起來像下面這個樣子:
Figure 29. 合併了dumbidea
和iss91v2
分支以後的提交歷史咱們將會在 分佈式 Git 中向你揭示更多有關分支工做流的細節,所以,請確保你閱讀完那個章節以後,再來決定你的下個項目要使用什麼樣的分支策略(branching scheme)。
請牢記,當你作這麼多操做的時候,這些分支所有都存於本地。 當你新建和合並分支的時候,全部這一切都只發生在你本地的 Git 版本庫中 —— 沒有與服務器發生交互。
7 ,遠程分支
移到上面去
8,變基 (rebase) : 從新設置基底
參考文章:https://backlog.com/git-tutorial/tw/stepup/stepup2_8.html
http://gitbook.liuhui998.com/4_2.html
8.1,變基的含義理解:
假設一個主分支master在提交C3的地方新開闢了一個分支test,而後test分支修改提交了一次C4,而後返回mater分支修改提交了一次C5。變基就是指將一個分支(好比test)中的異於另外一個分支(好比master)中的全部提交(即C4)按原有次序應用到另外一個分支上(拼接到最新的地方以後,即C3-->C5-->C4)。變基好以後兩個分支即是在同一條串線上的了(test在新maser在舊,原來test上的提交都被消除了,master依然在原來的地方上),合併即可以fast-forward了。這麼作的好處是提交歷史沒有分支了(某個提交有兩個父提交的狀況不存在了)。具體代碼以下:
- git checkout test //切換到test分支
- git rebase master //將當前分支(test)變基到基底(master)分支,此處可能有衝突,須要手動解決,解決以後用git add標記衝突已解決(add後不要commit),而後用git rebase --continue命令 繼續rebase。這一步的具體實現過程以下:將test 分支裏的每一個提交取消掉,而且把他們臨時保存爲補丁(patch,這些補丁放在.git/rebase 目錄中),而後把test分支更新到最新的maser分支(這裏用master的最新的commitID也能夠,並且更顯示了這個操做的本質),最後把保存的這些補丁應用到 test分支上。
- git checkout master //切換到master分支
- git merge test //將test分支合併到當前的master分支上,模式爲fast-forward
第二步以後的log狀況以下:C3-->C5(master的HEAD指向此處)-->C4(test的HEAD指向此處)。第4步fast-forward將master的HEAD前移到C4,和test分支的HEAD指向同一個commit(C4)。
關於第二點說明一下,如有衝突,git add 標記衝突解決後,其實能夠commit。若是不提交直接使用git rebase --continue,git會本身使用原來的提交信息提交掉,而後應用下一個補丁;若是本身手動提交,再使用git rebase --continue會提示你當前的這個補丁沒有什麼能夠作的(也就是暫存區沒有內容,其實你已經手動打上這個補丁了),因此此時你須要使用git rebase --skip來忽略這個補丁以使git繼續應用下一個補丁。這個--continue和交互式裏的--continue是不太同樣的。
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=,
8.2 git rebase master test
將test分支變基到master分支上,至關於兩個命令:①git checkout test ;②git rebase master。執行完後,當前分支會變爲test(不管開始時是在哪一個分支上)。
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
8.3, 參看下圖,master分支在C2位置分出一個server分支,server分支上的C3提交處又分出clinet分支。如今的需求是將只屬於client的提交(即C8,C9)合併到master分支上。方法以下:
git rebase --onto master server client
這個命令的意思是:取出client 分支(即git checkout client,會自動切換到client分支),找到client分支和server分支的共同祖先以後的修改,而後把它們在master分支上重放一遍(即合併到master分支上)。而後就能夠切回到master分支,合併client分支(fast-forward)。
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==================---------------------------==========
8.4, 交互式變基(git rebase -i 或git rebase --interactive )
交互式使用git rebase過程很差敘述,本身去慢慢體驗。說一點交互式的時候
- ①使用git rebase --continue實際就是使用git commit --amend,而後繼續下一個操做;
- ②若是修改了以後本身手動提交則會在原來的那個提交上多一個提交,其他沒什麼區別。這個--continue和非交互式使用git rebase裏的--continue是不太同樣的。
另外,修改好某個commit以後再使用git rebase --continue的時候如有衝突,解決衝突,標記衝忽然 後
- ①再使用git rebase --continue其實是對原來那個commit更加嶄新的一個commit上使用git commit --amend。
- ②解決衝突,標記衝突後 本身手動提交,和使用git rebase --continue是同樣的效果,都是覆蓋掉更加嶄新的那個提交。
- ③解決衝突,標記衝突後 ,若手動使用git commit --amend 則更加嶄新的那個提交會消失。仍是不太理解其中的基本原理。先記着現象
實際上,在rebase以前的提交會以ORIG_HEAD之名存留。若是rebase以後沒法復原到原先的狀態,能夠用git reset --hard ORIG_HEAD復原到rebase以前的狀態。
8.5,變基的風險
不要對在你的倉庫外有副本的分支執行變基。
若是你遵循這條金科玉律,就不會出差錯。 不然,人民羣衆會仇恨你,你的朋友和家人也會嘲笑你,唾棄你。
變基操做的實質是丟棄一些現有的提交,而後相應地新建一些內容同樣但實際上不一樣的提交。 若是你已經將提交推送至某個倉庫,而其餘人也已經從該倉庫拉取提交併進行了後續工做,此時,若是你用
git rebase
命令從新整理了提交併再次推送,你的同伴所以將不得再也不次將他們手頭的工做與你的提交進行整合,若是接下來你還要拉取並整合他們修改過的提交,事情就會變得一團糟。
第三部分:分佈式Git
1, 向一個項目貢獻
git diff --check 在git add前使用此命令能夠檢查令其餘開發者惱怒的空白問題。若是git add過了,能夠使用git diff --cached/--staged --check。
1.1, 私有小型團隊(*就是如今的狀況..)
※本身總結幾句:
git pull 等於兩個命令①git fetch ②git merge origin/master(在master分支上執行)
git push實際上就是在origin/master分支上執行git merge master,只有當是fast-forward模式時才容許push。git push 以後origin/master分支自動指向master的最前端提交。
你可能會遇到的最簡單的配置是有一兩個其餘開發者的私有項目。 「私有」 在這個上下文中,意味着閉源 - 不能夠從外面的世界中訪問到。 你和其餘的開發者都有倉庫的推送權限。
在這個環境下,能夠採用一個相似使用 Subversion 或其餘集中式的系統時會使用的工做流程。 依然能夠獲得像離線提交、很是容易地新建分支與合併分支等高級功能,可是工做流程能夠是很簡單的;主要的區別是合併發生在客戶端這邊而不是在提交時發生在服務器那邊。 讓咱們看看當兩個開發者在一個共享倉庫中一塊兒工做時會是什麼樣子。 第一個開發者,John,克隆了倉庫,作了改動,而後本地提交。 (爲了縮短這些例子長度,協議信息已被替換爲
...
。)# John's Machine $ git clone john@githost:simplegit.git Initialized empty Git repository in /home/john/simplegit/.git/ ... $ cd simplegit/ $ vim lib/simplegit.rb $ git commit -am 'removed invalid default value' [master 738ee87] removed invalid default value 1 files changed, 1 insertions(+), 1 deletions(-)第二個開發者,Jessica,作了一樣的事情 - 克隆倉庫並提交了一個改動:
# Jessica's Machine $ git clone jessica@githost:simplegit.git Initialized empty Git repository in /home/jessica/simplegit/.git/ ... $ cd simplegit/ $ vim TODO $ git commit -am 'add reset task' [master fbff5bc] add reset task 1 files changed, 1 insertions(+), 0 deletions(-)如今,Jessica 把她的工做推送到服務器上:
# Jessica's Machine $ git push origin master ... To jessica@githost:simplegit.git 1edee6b..fbff5bc master -> masterJohn 也嘗試推送他的改動:
# John's Machine $ git push origin master To john@githost:simplegit.git ! [rejected] master -> master (non-fast forward) error: failed to push some refs to 'john@githost:simplegit.git'不容許 John 推送是由於在同一時間 Jessica 已經推送了。 若是以前習慣於用 Subversion 那麼理解這點特別重要,由於你會注意到兩個開發者並無編輯同一個文件。 儘管 Subversion 會對編輯的不一樣文件在服務器上自動進行一次合併,但 Git 要求你在本地合併提交。 John 必須抓取 Jessica 的改動併合並它們,才能被容許推送。
$ git fetch origin ... From john@githost:simplegit + 049d078...fbff5bc master -> origin/master在這個時候,John 的本地倉庫看起來像這樣:
Figure 58. John 的分叉歷史John 有一個引用指向 Jessica 推送上去的改動,可是他必須將它們合併入本身的工做中以後才能被容許推送。
$ git merge origin/master Merge made by recursive. TODO | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)合併進行地很順利 - John 的提交歷史如今看起來像這樣:
Figure 59. 合併了origin/master
以後 John 的倉庫如今,John 能夠測試代碼,確保它依然正常工做,而後他能夠把合併的新工做推送到服務器上:
$ git push origin master ... To john@githost:simplegit.git fbff5bc..72bbc59 master -> master最終,John 的提交歷史看起來像這樣:
Figure 60. 推送到origin
服務器後 John 的歷史在此期間,Jessica 在一個特性分支上工做。 她建立了一個稱做
issue54
的特性分支而且在那個分支上作了三次提交。 她尚未抓取 John 的改動,因此她的提交歷史看起來像這樣:
Figure 61. Jessica 的特性分支Jessica 想要與 John 同步,因此她進行了抓取操做:
# Jessica's Machine $ git fetch origin ... From jessica@githost:simplegit fbff5bc..72bbc59 master -> origin/master那會同時拉取 John 推送的工做。 Jessica 的歷史如今看起來像這樣:
Figure 62. 抓取 John 的改動後 Jessica 的歷史Jessica 認爲她的特性分支已經準備好了,可是她想要知道必須合併什麼進入她的工做才能推送。 她運行
git log
來找出:$ git log --no-merges issue54..origin/master commit 738ee872852dfaa9d6634e0dea7a324040193016 Author: John Smith <jsmith@example.com> Date: Fri May 29 16:01:27 2009 -0700 removed invalid default value
issue54..origin/master
語法是一個日誌過濾器,要求 Git 只顯示全部在後面分支(在本例中是origin/master
)但不在前面分支(在本例中是issue54
)的提交的列表。 咱們將會在 提交區間 中詳細介紹這個語法。目前,咱們能夠從輸出中看到有一個 John 生成的可是 Jessica 尚未合併入的提交。 若是她合併
origin/master
,也就是說將會修改她的本地工做的那個單個提交。如今,Jessica 能夠合併她的特性工做到她的 master 分支,合併 John 的工做(
origin/master
)進入她的master
分支,而後再次推送回服務器。 首先,爲了整合全部這些工做她切換回她的 master 分支。$ git checkout master Switched to branch 'master' Your branch is behind 'origin/master' by 2 commits, and can be fast-forwarded.她既能夠先合併
origin/master
也能夠先合併issue54
- 它們都是上游,因此順序並無關係。 不論她選擇的順序是什麼最終的結果快照是徹底同樣的;只是歷史會有一點輕微的區別。 她選擇先合併入issue54
:$ git merge issue54 Updating fbff5bc..4af4298 Fast forward README | 1 + lib/simplegit.rb | 6 +++++- 2 files changed, 6 insertions(+), 1 deletions(-)沒有發生問題;如你所見它是一次簡單的快進。 如今 Jessica 合併入 John 的工做(
origin/master
):$ git merge origin/master Auto-merging lib/simplegit.rb Merge made by recursive. lib/simplegit.rb | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)每個文件都乾淨地合併了,Jessica 的歷史看起來像這樣:
Figure 63. 合併了 John 的改動後 Jessica 的歷史如今
origin/master
是能夠從 Jessica 的master
分支到達的,因此她應該能夠成功地推送(假設同一時間 John 並無再次推送):$ git push origin master ... To jessica@githost:simplegit.git 72bbc59..8059c15 master -> master每個開發者都提交了幾回併成功地合併了其餘人的工做。
Figure 64. 推送全部的改動回服務器後 Jessica 的歷史這是一個最簡單的工做流程。 你一般在一個特性分支工做一下子,當它準備好整合時合併回你的 master 分支。 當想要共享工做時,將其合併回你本身的 master 分支,若是有改動的話而後抓取併合並
origin/master
,最終推送到服務器上的master
分支。 一般順序像這樣:
Figure 65. 一個簡單的多人 Git 工做流程的一般事件順序
2, 維護項目(做爲管理者管理項目)
2.1,
git apply
git log branchA --not branchB //顯示在branchA中在不在branchB中的提交。
git log branchB..branchA //和上面的效果同樣,顯示在後面分支但不在前面分支的提交。
git log -p //-p選項會顯示每次提交所引入的差別
git diff branchA // 以branchA爲基準,比較當前分支和branchA分支的差別。
git diff branchA branchB // 以branchA爲基準,比較branchB和branchA的差別。
2.2 合併分支前,肯定特性分支中引入的那些內容
實際上就是將特性分支(topic)的最新提交與兩個分支的共同祖先提交進行比對。能夠有兩種方法:
①,手動找出公共祖先,而後比對
- git merge-base topic master //這個命令用於找到topic和master分支的共同祖先提交(之前就是兩個分支合併的基準提交),這個命令會返回共同祖先的提交哈希值hash1。
- git diff hash1 //以hash1提交爲基準,比較當前分支的最新提交與其的差別。
②,上面的作法比較麻煩,Git提供了一種比較便捷的方式:三點語法。
- git diff master...topic //該命令會將topic分支的最新提交與兩個分支的共同祖先(假設爲A)提交作比對,以A爲基準,即git diff A topic
2.3 合併工做流
合併工做流有不少種方式,但其實質就是合併各個不一樣的分支。如下選取幾個典型的工做流加以說明:
工做流1:release 分支是長期分支,用於發佈。其他的分支在此基礎上開發,開發分支完成後合併到release分支上去。這是最簡單的一種方式,但風險也大。這種方式適合一我的開發,沒有其餘人干擾你的代碼。
工做流2(中小型項目最經常使用):有兩個長期分支:release和develop。release用於發佈,develop用於測試,其他的topic分支用於開發。當開發完成後將各個topic分支合併入develop分支,測試沒有問題以後再將develop合併入release分支(此時是fast-forward模式)。圖形表示以下:
如圖,master分支一直提交到C2,此時須要協同開發或者是須要開闢新的分支作些開發,在master的基礎上檢出develop分支用於發佈前的測試,其他的topic開發分支也在master分支上checkout出來,之後各個topic分支開發完成後直接合併入develop分支,develop分支測試沒問題以後再將master分支快進到develop的HEAD處。
工做流3:大項目工做流
就是分支更多了,有四個長期分支:
master
、next
,用於新工做的pu
(proposed updates)和用於維護性向後移植工做(maintenance backports)的maint
分支。具體不敘述了。2.4 變基與挑選工做流
①本身理解:
git cherry-pick commitID //此命令會將指定的提交commitID應用到當前分支上。有可能會有衝突,按提示操做便可。
上面這個操做也能夠用變基完成,具體操做步驟以下:
假設狀況以下面圖80所示,一樣只想把ruby_client分支中的e43a6提交提取出來合併到master分支,
- git rebase -i f42c5 //這是在ruby_client分支上執行的,此語句會將二者共同祖先以後的ruby_client分支上的全部提交顯示出來,而後在編輯器裏將5ddae刪除就能夠只將e43a6提交變基到master上,此時有衝突解決而後continue,而後將mater快進到ruby_client分支,而後刪除ruby_client分支便可。
- 上面的命令有如下幾個同義語句:
- git rebase -i f42c5 //ruby_client分支上執行
- git rebase -i master //ruby_client分支上執行
- git rebase -i master或f42c5 ruby_client //這個命令能夠在任何分支上執行,執行事後會自動切換到ruby_client分支
②摘抄:
爲了保持線性的提交歷史,有些維護者更喜歡在 master 分支上對貢獻過來的工做進行變基和揀選,而不是直接將其合併。變基前面說過了,下面說說挑選:
Git 中的揀選相似於對特定的某次提交的變基。 它會提取該提交的補丁,以後嘗試將其從新應用到當前分支上。 這種方式在你只想引入特性分支中的某個提交,或者特性分支中只有一個提交,而你不想運行變基時頗有用。 舉個例子,假設你的項目提交歷史相似:
若是你但願將提交
e43a6
拉取到 master 分支,你能夠運行:$ git cherry-pick e43a6fd3e94888d76779ad79fb568ed180e5fcdf Finished one cherry-pick. [master]: created a0a41a9: "More friendly message when locking the index fails." 3 files changed, 17 insertions(+), 3 deletions(-)
這樣會拉去和 e43a6相同的更改,可是由於應用的日期不一樣,你會獲得一個新的SHA-1值。
而後你就能夠刪除ruby_client這個特性分支,並丟棄不想拉入的提交。
2.5 爲發佈打標籤 略
2.6 生成一個構建號
Git 中不存在隨每次提交遞增的「v123」之類的數字序列,若是你想要爲提交附上一個可讀的名稱,能夠對其運行
git describe
命令。 Git 將會給出一個字符串,它由最近的標籤名、自該標籤以後的提交數目和你所描述的提交的部分 SHA-1 值構成:$ git describe master v1.6.2-rc1-20-g8c5b85c這樣你在導出一個快照或構建時,能夠給出一個便於人們理解的命名。 實際上,若是你的 Git 是從 Git 本身的版本庫克隆下來並構建的,那麼
git --version
命令給出的結果是與此相似的。 若是你所描述的提交自身就有一個標籤,那麼它將只會輸出標籤名,沒有後面兩項信息。注意
git describe
命令只適用於有註解的標籤(即便用-a
或-s
選項建立的標籤),因此若是你在使用git describe
命令的話,爲了確保能爲標籤生成合適的名稱,打發布標籤時都應該採用加註解的方式。 你也能夠使用這個字符串來調用 checkout 或 show 命令,可是這依賴於其末尾的簡短 SHA-1 值,所以不必定一直有效。 好比,最近 Linux 內核爲了保證 SHA-1 值對象的惟一性,將其位數由 8 位擴展到了 10 位,致使之前的git describe
輸出所有失效。2.7 準備一次發佈
如今你能夠發佈一個構建了。 其中一件事情就是爲那些不使用 Git 的可憐包們建立一個最新的快照歸檔。 使用
git archive
命令完成此工做:$ git archive master --prefix='project/' | gzip > `git describe master`.tar.gz $ ls *.tar.gz v1.6.2-rc1-20-g8c5b85c.tar.gz將項目中的全部文件放入一個名爲 --prefix描述的文件夾內。
若是有人將這個壓縮包解壓,他就能夠獲得你的項目文件夾的最新快照。 你也能夠以相似的方式建立一個 zip 壓縮包,但此時你應該向
git archive
命令傳遞--format=zip
選項:$ git archive master --prefix='project/' --format=zip > `git describe master`.zip如今你有了本次發佈的一個 tar 包和一個 zip 包,能夠將其上傳到網站或以電子郵件的形式發送給人們。
2.8 製做提交簡報
如今是時候通知郵件列表裏那些好奇你的項目發生了什麼的人了。 使用
git shortlog
命令能夠快速生成一份包含從上次發佈以後項目新增內容的修改日誌(changelog)類文檔。 它會對你給定範圍內的全部提交進行總結;好比,你的上一次發佈名稱是 v1.0.1,那麼下面的命令能夠給出上次發佈以來全部提交的總結:$ git shortlog --no-merges master --not v1.0.1 Chris Wanstrath (8): Add support for annotated tags to Grit::Tag Add packed-refs annotated tag support. Add Grit::Commit#to_patch Update version and History.txt Remove stray `puts` Make ls_tree ignore nils Tom Preston-Werner (4): fix dates in history dynamic version method Version bump to 1.0.2 Regenerated gemspec for version 1.0.2這份整潔的總結包括了自 v1.0.1 以來的全部提交,而且已經按照做者分好組,你能夠經過電子郵件將其直接發送到列表中。
第四部分,Github
第五部分, Git 工具
1 選擇修訂版本
git show <commit / tag /branch/ head / head^ ....>
分支名能夠代替這個分支的最後一個提交對象(的SHA-1)
git rev-parse branchname // 顯示出指定的branch所指向的提交對象
1.1, 引用日誌
當你在工做時, Git 會在後臺保存一個引用日誌(reflog),引用日誌記錄了最近幾個月你的 HEAD 和分支引用所指向的歷史。
你能夠使用
git reflog
來查看引用日誌$ git reflog 734713b HEAD@{0}: commit: fixed refs handling, added gc auto, updated d921970 HEAD@{1}: merge phedders/rdocs: Merge made by recursive. 1c002dd HEAD@{2}: commit: added some blame and merge stuff 1c36188 HEAD@{3}: rebase -i (squash): updating HEAD 95df984 HEAD@{4}: commit: # This is a combination of two commits. 1c36188 HEAD@{5}: rebase -i (squash): updating HEAD 7e05da5 HEAD@{6}: rebase -i (pick): updating HEAD每當你的 HEAD 所指向的位置發生了變化,Git 就會將這個信息存儲到引用日誌這個歷史記錄裏。 經過這些數據,你能夠很方便地獲取以前的提交歷史。 若是你想查看倉庫中 HEAD 在五次前的所指向的提交,你能夠使用
@{n}
來引用 reflog 中輸出的提交記錄。$ git show HEAD@{5}你一樣能夠使用這個語法來查看某個分支在必定時間前的位置。 例如,查看你的
master
分支在昨天的時候指向了哪一個提交,你能夠輸入$ git show master@{yesterday}就會顯示昨天該分支的頂端指向了哪一個提交。 這個方法只對還在你引用日誌裏的數據有用,因此不能用來查好幾個月以前的提交。
能夠運行
git log -g
來查看相似於git log
輸出格式的引用日誌信息:$ git log -g master commit 734713bc047d87bf7eac9674765ae793478c50d3 Reflog: master@{0} (Scott Chacon <schacon@gmail.com>) Reflog message: commit: fixed refs handling, added gc auto, updated Author: Scott Chacon <schacon@gmail.com> Date: Fri Jan 2 18:32:33 2009 -0800 fixed refs handling, added gc auto, updated tests commit d921970aadf03b3cf0e71becdaab3147ba71cdef Reflog: master@{1} (Scott Chacon <schacon@gmail.com>) Reflog message: merge phedders/rdocs: Merge made by recursive. Author: Scott Chacon <schacon@gmail.com> Date: Thu Dec 11 15:08:43 2008 -0800 Merge commit 'phedders/rdocs'值得注意的是,引用日誌只存在於本地倉庫,一個記錄你在你本身的倉庫裏作過什麼的日誌。 其餘人拷貝的倉庫裏的引用日誌不會和你的相同;而你新克隆一個倉庫的時候,引用日誌是空的,由於你在倉庫裏尚未操做。
git show HEAD@{2.months.ago}
這條命令只有在你克隆了一個項目至少兩個月時纔會有用——若是你是五分鐘前克隆的倉庫,那麼它將不會有結果返回。1.2,祖先引用
HEAD^表示"HEAD的父提交",固然也能夠用commitID^
HEAD^2表示"HEAD的的第二父提交", 這個語法只適用於合併(merge)的提交,由於合併提交會有多個父提交。第一父提交是你合併時所在分支,第二父提交是你所合併的分支。
HEAD~一樣指向第一父提交,所以HEAD~和HEAD^是等價的。
HEAD~2(也可用HEAD~~)表示第一父提交的第一父提交,也就是祖父提交。等價於HEAD^^,即第一父提交的第一父提交。
HEAD~3^2表示HEAD的第三個第一個父提交的第二父提交.
1.3, 提交區間(即一次能夠選擇到多個提交對象)
你已經學會如何指定單次的提交,如今來看看如何指明必定區間的提交。 當你有不少分支時,這對管理你的分支時十分有用,你能夠用提交區間來解決 「這個分支還有哪些提交還沒有合併到主分支?」 的問題
雙點(..)
最經常使用的指明提交區間語法是雙點。 這種語法可讓 Git 選出在一個分支中而不在另外一個分支中的提交。 例如,你有以下的提交歷史 Example history for range selection.
Figure 137. Example history for range selection.你想要查看 experiment 分支中還有哪些提交還沒有被合併入 master 分支。 你能夠使用
master..experiment
來讓 Git 顯示這些提交。也就是 「在 experiment 分支中而不在 master 分支中的提交」。 爲了使例子簡單明瞭,我使用了示意圖中提交對象的字母來代替真實日誌的輸出,因此會顯示:$ git log master..experiment D C反過來,若是你想查看在
master
分支中而不在experiment
分支中的提交,你只要交換分支名便可。experiment..master
會顯示在master
分支中而不在experiment
分支中的提交:$ git log experiment..master F E這可讓你保持
experiment
分支跟隨最新的進度以及查看你即將合併的內容。 另外一個經常使用的場景是查看你即將推送到遠端的內容:$ git log origin/master..HEAD這個命令會輸出在你當前分支中而不在遠程
origin
中的提交。 若是你執行了git push
而且你的當前分支正在跟蹤origin/master
,git log origin/master..HEAD
所輸出的提交將會被傳輸到遠端服務器。 若是你留空了其中的一邊, Git 會默認爲 HEAD。 例如,git log origin/master..
將會輸出與以前例子相同的結果 —— Git 使用 HEAD 來代替留空的一邊。
多點
雙點語法很好用,但有時候你可能須要兩個以上的分支才能肯定你所須要的修訂,好比查看哪些提交是被包含在某些分支中的一個,可是不在你當前的分支上。 Git 容許你在任意引用前加上
^
字符或者--not
來指明你不但願提交被包含其中的分支。 所以下列3個命令是等價的:$ git log refA..refB $ git log ^refA refB $ git log refB --not refA這個語法很好用,由於你能夠在查詢中指定超過兩個的引用,這是雙點語法沒法實現的。 好比,你想查看全部被
refA
或refB
包含的可是不被refC
包含的提交,你能夠輸入下面中的任意一個命令$ git log refA refB ^refC $ git log refA refB --not refC這就構成了一個十分強大的修訂查詢系統,你能夠經過它來查看你的分支裏包含了哪些東西。
三點
[自注]:git log 與 git diff中的三點語法不太同樣,git log 是顯示兩個分支中各自獨有的提交,git diff是顯示公共祖先 與指定的分支(三個點後面的那個分支)的差別
最後一種主要的區間選擇語法是三點,這個語法能夠選擇出被兩個引用中的一個包含但又不被二者同時包含的提交。 再看看以前雙點例子中的提交歷史。 若是你想看
master
或者experiment
中包含的但不是二者共有的提交,你能夠執行$ git log master...experiment F E D C這和一般
log
按日期排序的輸出同樣,僅僅給出了4個提交的信息。這種情形下,
log
命令的一個經常使用參數是--left-right
,它會顯示每一個提交到底處於哪一側的分支。 這會讓輸出數據更加清晰。$ git log --left-right master...experiment < F < E > D > C有了這些工具,你就能夠十分方便地查看你 Git 倉庫中的提交。
2 交互式暫存
git add -i //會進行交互式暫存,感受沒啥用,不用交互式也都能完成其功能。
git add -p [file....] 或 git add --patch [file....]能夠交互式的作部分文件暫存,即一次只暫存一個文件中若干個部分改動,而不是所有改動。
更進一步地,能夠使用
reset --patch
命令的補丁模式來部分重置文件,經過checkout --patch
命令來部分檢出文件與stash save --patch
命令來部分暫存文件。 咱們將會在接觸這些命令的高級使用方法時瞭解更多詳細信息。
3 儲藏與清理
切換分支前,若是工做目錄是髒的狀態----即,工做區有未提交狀態的文件(包括未暫存的和暫存了沒有提交兩種狀態的文件)---是沒法直接切換的。此時能夠經過git stash 將髒的狀態 保存在一個棧上,之後任什麼時候間均可以從新應用(恢復)這些儲藏。固然stash的應用場景不僅是切換分支時。
git stash 或 git stash save // 儲藏文件
git stash list //查看儲藏的東西
恢復儲藏能夠在任什麼時候間任何位置任何狀態,有兩種方法恢復(應用)儲藏:
①
- git stash apply [stashID] [--index] //應用[可選]指定的stashID(形如stash@{n})到當前工做目錄,若是不指定則應用最新的那個(即stash@{0})。--index選項是可選的,若是不加此選項,stash前如有暫存的文件,應用儲藏後都會變爲未暫存的狀態,有了此選項則會正常恢復。
- git stash drop [stashID] //git stash apply只會嘗試應用儲藏,在堆棧上還有它。運行git stash drop 能夠移除指定的儲藏,不指定則移除最新的那個。
②git stash pop [--index] //這個命令至關於上面兩個命令。即應用儲藏而後當即從棧上扔掉它。
※儲藏的變種(即加上各類參數)
git stash --keep-index // 此參數告訴Git不要儲藏任何你經過git add命令已暫存的東西。注意,這裏能夠了解到一點:暫存區實際也是索引區,index和stage某種意義上在git中是同義的。
git stash --include-untracked(或-u參數) //默認狀況下git stash只會儲藏已經在索引(已經暫存過)中的的文件,加上這個 參數以後Git也會儲藏任何建立的未跟蹤文件。
git stash --patch //
--patch
標記,Git 不會儲藏全部修改過的任何東西,可是會交互式地提示哪些改動想要儲藏、哪些改動須要保存在工做目錄中。git stash branch [branchname] //建立一個新的分支並檢出儲藏所在的分支並將儲藏在新分支上應用,而後應用成功後扔掉儲藏。這個命令應用前應該已經儲藏過一些東西了。git branch name是在當前分支基礎上建立一個新的分支(工做目錄必須是乾淨的),git stash branch name也是這個功能,可是它建立的這個分支還包括工做區中的髒狀態(首先要被stash起來)。
※清理工做目錄
git clean
- 使用這個命令前必定要使用-n選項來「作一次演習而後告訴你 將要 移除什麼」。
- 另外一個當心處理過程的方式是使用
-i
或 「interactive」,這將會交互式的運行clean命令。- 你須要謹慎地使用這個命令,由於它被設計爲從工做目錄中移除未被追蹤的文件。 若是你改變主意了,你也不必定能找回來那些文件的內容。 一個更安全的選項是運行
git stash --all
來移除每同樣東西並存放在棧中。- -d選項能夠刪除未跟蹤的文件夾
- -f選項 強制移除
- 默認狀況下,
git clean
命令只會移除沒有忽略的未跟蹤文件。 任何與.gitiignore
或其餘忽略文件中的模式匹配的文件都不會被移除。 若是你也想要移除那些文件,例如爲了作一次徹底乾淨的構建而移除全部由構建生成的.o
文件,能夠給 clean 命令增長一個-x
選項。
4 簽署工做(略)
gpg --gen-key
gpg --list-keys
git tag -s
git tag -v
5 搜索
不管倉庫裏的代碼量有多少,你常常須要查找一個函數是在哪裏調用或者定義的,或者一個方法的變動歷史。 Git 提供了兩個有用的工具來快速地從它的數據庫中瀏覽代碼和提交。
5.1, Git Grep
此命令能夠很方便地從提交歷史或者工做目錄中查找一個字符串或者正則表達式。默認狀況下 Git 會查找你工做目錄的文件。一些經常使用選項參數以下:
- 你能夠傳入
-n
參數來輸出 Git 所找到的匹配行行號。- 你能夠使用
--count
選項來使 Git 輸出概述的信息,僅僅包括哪些文件包含匹配以及每一個文件包含了多少個匹配。- 若是你想看匹配的行是屬於哪個方法或者函數,你能夠傳入
-p
選項。相比於一些經常使用的搜索命令好比
grep
和ack
,git grep
命令有一些的優勢。 第一就是速度很是快,第二是你不只僅能夠能夠搜索工做目錄,還能夠搜索任意的 Git 樹。5.2 Git日誌搜索
5.2.1 或許你不想知道某一項在 哪裏 ,而是想知道是什麼 時候 存在或者引入的。
git log
命令有許多強大的工具能夠經過提交信息甚至是 diff 的內容來找到某個特定的提交。例如,若是咱們想找到
ZLIB_BUF_MAX
常量是何時引入的,咱們能夠使用-S
選項來顯示新增和刪除該字符串的提交。git log -SZLIB_BUF_MAX --oneline
若是你但願獲得更精確的結果,你能夠使用
-G
選項來使用正則表達式搜索。
5.2.2 行日誌搜索
是另外一個至關高級而且有用的日誌搜索功能。 這是一個最近新增的不太知名的功能,但倒是十分有用。 在
git log
後加上-L
選項便可調用,它能夠展現代碼中一行或者一個函數的歷史。例如,假設咱們想查看
zlib.c
文件中`git_deflate_bound` 函數的每一次變動,咱們能夠執行git log -L :git_deflate_bound:zlib.c
。 Git 會嘗試找出這個函數的範圍,而後查找歷史記錄,而且顯示從函數建立以後一系列變動對應的補丁。$ git log -L :git_deflate_bound:zlib.c commit ef49a7a0126d64359c974b4b3b71d7ad42ee3bca Author: Junio C Hamano <gitster@pobox.com> Date: Fri Jun 10 11:52:15 2011 -0700 zlib: zlib can only process 4GB at a time diff --git a/zlib.c b/zlib.c --- a/zlib.c +++ b/zlib.c @@ -85,5 +130,5 @@ -unsigned long git_deflate_bound(z_streamp strm, unsigned long size) +unsigned long git_deflate_bound(git_zstream *strm, unsigned long size) { - return deflateBound(strm, size); + return deflateBound(&strm->z, size); } commit 225a6f1068f71723a910e8565db4e252b3ca21fa Author: Junio C Hamano <gitster@pobox.com> Date: Fri Jun 10 11:18:17 2011 -0700 zlib: wrap deflateBound() too diff --git a/zlib.c b/zlib.c --- a/zlib.c +++ b/zlib.c @@ -81,0 +85,5 @@ +unsigned long git_deflate_bound(z_streamp strm, unsigned long size) +{ + return deflateBound(strm, size); +} +若是 Git 沒法計算出如何匹配你代碼中的函數或者方法,你能夠提供一個正則表達式。 例如,這個命令和上面的是等同的:
git log -L '/unsigned long git_deflate_bound/',/^}/:zlib.c
。 你也能夠提供單行或者一個範圍的行號來得到相同的輸出。
6 重寫歷史
7 重置揭密
8 高級合併
9 Rerere
10 使用 Git 調試
11 子模塊
12 打包
13 替換
14 憑證存儲
15 總結
1