Git學習筆記

Git安裝

linuxhtml

$ sudo yum install git

mac: http://git-scm.com/download/macjava

windows: http://git-scm.com/download/winjquery

git官方文檔: https://git-scm.com/book/zh/v2linux

Git安裝完以後,須要作最後一步配置,若是你沒有作這項配置,是沒有git公鑰和私鑰的,而上傳代碼到遠程倉庫的時候須要祕鑰進行驗證是否本人上傳的,想要建立可使用下面的方法:git

打開git bash,分別執行如下兩句命令
git config --global user.name 「用戶名」
git config --global user.email 「郵箱」

config 的三個做用域github

--local 只對某個倉庫有效
--global 對當前用戶全部倉庫有效
--system 對系統全部登陸的用戶有效
--list

SSH配置

  1. 打開git bash。
  2. 使用cd ~/.ssh能夠查看是否已配置SSH。
  3. 執行生成公鑰和私鑰的命令ssh-keygen -t rsa 並按回車3下(爲何按三下,是由於有提示你是否須要設置密碼,若是設置了每次使用Git都會用到密碼,通常都是直接不寫爲空,直接回車就行了)。會在一個文件夾裏面生成一個私鑰 id_rsa和一個公鑰id_rsa.pub。(可執行start ~命令,生成的公私鑰在 .ssh的文件夾裏面)。
  4. .ssh若是不作特殊處理的話,通常是在C:\Users\Administrator目錄下。若是看不到.ssh文件,可使用ls -ah指令查看隱藏文件夾便可,這是存放祕鑰的文件,打開這個文件會看到id_rsa和id_rsa.pub。id_rsa是私鑰文件,id_rsa.pub是公鑰文件。
  5. 執行查看公鑰的命令cat ~/.ssh/id_rsa.pub

建Git倉庫

兩種場景:web

1.把已有的項目代碼歸入Git管理shell

cd 項目代碼所在的文件夾
git init

2.創建新的項目直接用Git管理segmentfault

cd 某個文件夾
git init your_project #會在當前路徑下建立和項目名相同的文件夾
cd your_project
mkdir 建立目錄
echo "" > 文件名 建立文件
clear 清屏

在倉庫中添加文件windows

1.將文件拷貝到工做目錄

cp ... .

2.測試文件符合要求後添加到暫存目錄

git add files
git add -u 全部文件

3.查看文件是否被git管理

git status

4.提交暫存區的文件

git commit -m'更改理由' -am'..'從工做區直接提交

git add 更新將要提交的內容
git restore 放棄工做目錄中的更改
git rm 移除

Git和其餘版本控制系統如SVN的一個不一樣之處就是有暫存區的概念。

工做區(Working Directory)

就是你在電腦裏能看到的目錄,好比個人learngit文件夾就是一個工做區

版本庫(Repository)

工做區有一個隱藏目錄.git,這個不算工做區,而是Git的版本庫。

Git的版本庫裏存了不少東西,其中最重要的就是稱爲stage(或者叫index)的暫存區,還有Git爲咱們自動建立的第一個分支master,以及指向master的一個指針叫HEAD

img

git add把文件添加進去,實際上就是把文件修改添加到暫存區;

git commit提交更改,實際上就是把暫存區的全部內容提交到當前分支。

給文件重名名

git mv old new
操做完後commit提交

查看版本歷史,提交日誌

git log -n5 --oneline 最近5條 簡明 
git log --all --graph 全部分支 圖像化關係

版本歷史圖形化工具

gitk
查看分支
git branch -v
建立分支
git checkout -b 分支名 commitid
切換分支
git checkout 分支名

查看某個命令的幫助文檔

git help --web 命令  --web 在網頁

.git目錄

HEAD文件:指向瞭如今引用的分支

cat HEAD
ref: refs/heads/master

config文件:記錄了用戶的信息

refs/:引用目錄,包含了heads和tags目錄

​ tags:標籤 里程碑,項目開發到必定程度,給commit打一個標籤如[v1.0]

​ 標籤文件是tag類型 自己有一個40位的哈希值 ,內容包含了一個commit的類型的object

​ heads:分支,如先後端創建獨立的分支,互不影響,須要集成時可合併到一個公共的分支

​ 查看文件對象類型

cat 分支文件
git cat-file -t 哈希值
-p 看內容
若是哈希值足以保證惟一性可使用短的一部分

​ master文件爲commit類型

​ git branch -av查看分支能夠看到master分支引用指針就是heads目錄中master文件的哈希值

objects/:全部文件對象

git在每次commit的時候都會生成一個tree對象、一個parent對象(若是不是第一次提交的話)、和一個commit對象,這個最頂層的tree就是對應整個工做目錄,tree下面還有blob、tree對象,都是一串hash值指向對應的內容,當某個文件發生變更的時候會從新保存一次快照(hash),若是文件沒有發生變更,保留的快照依然是上次的。

鬆散對象 (loose object) 會被打包到pack/目錄

查看文件對象類型 爲:tree

git cat-file -t 文件名+哈希值

查看內容 包含一個blob文件,就是提交的內容

git cat-file -p 文件名+哈希值

git對象彼此的關係

每一次提交都會建立一個commit對象,一個commit對象對應包含一個tree對象,tree表明了當前時間點倉庫目錄結構的快照,blob指具體的文件,在git中若是兩個文件內容相同就看做一個文件,不論文件名

git分離頭指針

若是不當心經過git checkout命令切換到某個commit中(即HEAD指向某個commit),git會提示咱們正處於分離頭指針的狀態下(工做在沒有分支的狀況下),若是咱們作了大量的修改,可是某天咱們忽然又切換到另外一個commit時,咱們的修改就有可能被git當作垃圾清除掉,所以這個動做十分危險。

分離頭指針的用處:進行嘗試性的變動時

試着修改某些文件時,若是以爲修改的效果不滿意,能夠直接切換到別的分支,丟棄當前修改

若是咱們切換出去時,以爲當前的修改十分重要,就按照git的提示建立一個新分支

若是某個變動(提交)是很是重要的,那麼必定要跟某個分支綁定在一塊兒

建立新分支:

git checkout -b  新分支名稱  基於某個分支或者commit

eg:git checkout -b newBranch master

比較某兩個commit的區別

git diff 第一個commit 第二個commit

eg:git diff HEAD HEAD^1  (當前的HEAD指向的commit和他的父級進行比對)

HEAD^ ==HEAD~ == HEAD^1 == HEAD~1

HEAD^^ == HEAD^1^1 == HEAD^2

刪除不須要的分支

git branch -D 分支名

修改commit的message

對最近一次commit的message作變動

git commit --amend

更改以前的message

git rebase -i 需更改commit的父級id 
執行後進入編輯,把須要修改的一次message前面的'pick'改成'r'或'reword',保存退出,會跳轉到修改message

合併多個連續的commit

git rebase -i 父級commitid
執行後進入編輯,僅保留要合併到的commit的'pick',把須要須要合併的幾個'pick'改成's'或'squash',退出保存,修改說明

合併多個間隔的commit

首先git log --graph查看commit歷史

變基git rebase -i 父commitid進入vi

將父commitid拷貝進來並改變順序,放在要合併的commit上面

要合併的commit的'pick'改成's'

pick acf475ed #父commit
s 7ac3c1cb8b92 #要合併的commit
...其餘

保存退出後報錯:interactive rebase in progress; onto 7ac3c1c

而後執行git rebase --continue繼續變基,進入vi

怎加一個message,保存退出便可

其餘參考:https://segmentfault.com/a/11...

git處理合並衝突

什麼是合併衝突

在 Git 中,「合併(merging)」 是在形式上整合別的分支到你當前的工做分支的操做。你須要獲得在另一個上下文背景下的改動(這就也就是咱們所提到過的,一個有效的分支應該是創建在一個上下文工做背景上的),而且合併它們到你的當前的工做文件中來。

做爲你的版本管理系統,Git 所帶來的最偉大的改善就是它讓合併操做變得很是輕鬆簡單。在大多數狀況下,Git 會本身弄清楚該如何整合這些新來的變化。

固然,也存在極少數的狀況,你必須本身手動地告訴 Git 該怎麼作。最爲常見的就是你們都改動了同一個文件。即使在這種狀況下,Git 仍是有可能自動地發現並解決掉這些衝突。可是,若是兩我的同時更改了同一個文件的同一行代碼,或者一我的改動了那些被另外一我的刪除了的代碼,Git 就不能簡單地肯定到底誰的改動纔是正確的。這時 Git 會把這些地方標記爲一個衝突,你必須首先解決掉這些衝突,而後再繼續你的工做。
如何解決合併衝突

當面對一個合併衝突時,咱們首先要搞明白髮生了什麼。例如是否是你和你的同事都同時編輯了同一個文件的同一行代碼呢?是否是他刪除了一個你正在編輯的文件呢?是否是大家同時添加了一個相同文件名的文件呢?
當你使用 「git status」 時, Git 會告訴你存在一個 「未合併的路徑(unmerged paths)」,這只是用另一個方式告訴你,存在一個或多個衝突:

$ git status
# On branch contact-form
# You have unmerged paths.
#   (fix conflicts and run "git commit")
#
# Unmerged paths:
#   (use "git add <file>..." to mark resolution)
#
#       both modified:   contact.html
#
no changes added to commit (use "git add" and/or "git commit -a")1234567891011

就讓咱們來深刻地探討一下,如何去解決這些最多見的衝突。
當兩個改動發生在同一個文件的同一些行上,咱們就要看看發生衝突的文件的內容了。Git 會很是友好地把文件中那些有問題的區域在 「<<<<<<< HEAD」 和 「>>>>>>> [other/branch/name]」 之間標記出來。

第一個標記後的內容源於當前分支。在尖括號以後,Git 會告訴咱們這些改動是從哪裏(哪一個分支)來的。而後有衝突的改動會被 「=======」 分割起來。
如今,當清理文件並獲得最終代碼後,全部剩下的工做就是將這個結果保存起來,而且立刻退出這個合併工具。這樣 Git 就會知道你已經完成了這個操做。Git 會在後臺對那個文件自動地執行 「git add」 命令。這也標誌着衝突已經解決了。若是你使用合併工具,而是手動在文本編輯器中清理這些衝突,你必須手動地將文件標記爲已解決狀態(經過執行命令 「git add 」)。

最終,當全部的衝突被解決後,你必須經過一個正常的提交操做來完成這個清理合並衝突的工做。

如何撤銷一個合併

你應該始終牢記,你能夠在任什麼時候間執行撤銷操做,並返回到你開始合併以前的狀態。要對本身有信心,你不會破壞項目中的任何東西。只要在命令行界面中鍵入 「git merge –abort」 命令,你的合併操做就會被安全的撤銷。

當你解決完衝突,而且在合併完成後發現一個錯誤,你仍然仍是有機會來簡單地撤銷它。你只需要鍵入 「git reset –hard 」 命令,系統就會回滾到那個合併開始前的狀態,而後從新開始吧!

git status會有rebase in progress; onto ……這種問題? 該怎麼解決?

是你以前或者剛剛用過 git rebase,但上一次的進程尚未完成。

能夠直接 git rebase --abort 來取消目前的進程

比較暫存區和HEAD所含文件的差別

git diff --cached

比較工做區和暫存區所含文件的差別

git diff
git diff -- 可加具體文件名

讓暫存區恢復成和HEAD同樣

git reset HEAD

讓工做區恢復爲和暫存區同樣

git checkout -- 文件名

取消暫存區部分文件的更改

git reset HEAD -- 文件名

消除最近幾回的提交

git reset --hard commitid(想回到的commit狀態)

查看不一樣提交的指定文件的差別

git diff 分支名或commitid 分支名或commitid -- 指定文件

刪除文件的正確作法

git rm 文件名

開發中臨時加塞了緊急任務怎麼處理

場景:開發中有一部分文件已經放到了暫存區,一部分還在工做區修改當中,可是測試發現對應的分支是有問題的,須要臨時修復bug

1.先把手頭的工做備份到其餘地方git stash,能夠用git stash list查看

2.修復完bug提交後再恢復繼續

git stash apply stash列表中存放的文件仍會保留

git stash popstash列表中存放的文件會移除

指定不須要Git管理的文件

gitHub新建倉庫時會讓你配置一個.gitignore文件,針對不一樣的語言指定不被git管理的文件類型

只能夠命名爲.gitignore

如java

# Compiled class file
*.class
# Package Files #
*.jar
*.war
*.tar.gz
*.zip
...

將Git倉庫備份到本地

經常使用的傳輸協議

啞協議與智能協議

直觀區別:啞協議傳輸進度不可見,智能協議可見

傳輸速度:智能協議比啞協議塊

推薦使用智能協議

備份特色:多點備份

若是要和遠端的倉庫進行關聯的話,須要remote

git remote -v 查看
git remote add 名字 地址 新建遠端倉庫

當本地倉庫有新的分支,而遠端並未添加進去時,直接push

git push 遠端倉庫

Git遠程操做

git clone

遠程操做的第一步,一般是從遠程主機克隆一個版本庫,這時就要用到git clone命令。

$ git clone <版本庫的網址>

好比,克隆jQuery的版本庫。

$ git clone https://github.com/jquery/jquery.git

該命令會在本地主機生成一個目錄,與遠程主機的版本庫同名。若是要指定不一樣的目錄名,能夠將目錄名做爲git clone命令的第二個參數。

$ git clone <版本庫的網址> <本地目錄名>

git clone支持多種協議,除了HTTP(s)之外,還支持SSH、Git、本地文件協議等

git remote

爲了便於管理,Git要求每一個遠程主機都必須指定一個主機名。git remote命令就用於管理主機名。

不帶選項的時候,git remote命令列出全部遠程主機。

$ git remote
origin

使用-v選項,能夠參看遠程主機的網址。

$ git remote -v
origin  git@github.com:jquery/jquery.git (fetch)
origin  git@github.com:jquery/jquery.git (push)

上面命令表示,當前只有一臺遠程主機,叫作origin,以及它的網址。

克隆版本庫的時候,所使用的遠程主機自動被Git命名爲origin。若是想用其餘的主機名,須要用git clone命令的-o選項指定。

$ git clone -o jQuery https://github.com/jquery/jquery.git
$ git remote
jQuery

上面命令表示,克隆的時候,指定遠程主機叫作jQuery。

git remote show命令加上主機名,能夠查看該主機的詳細信息。

$ git remote show <主機名>

git remote add命令用於添加遠程主機。

$ git remote add <主機名> <網址>

git remote rm命令用於刪除遠程主機。

$ git remote rm <主機名>

git remote rename命令用於遠程主機的更名。

$ git remote rename <原主機名> <新主機名>

git fetch

一旦遠程主機的版本庫有了更新(Git術語叫作commit),須要將這些更新取回本地,這時就要用到git fetch命令。

$ git fetch <遠程主機名>

上面命令將某個遠程主機的更新,所有取回本地。

git fetch命令一般用來查看其餘人的進程,由於它取回的代碼對你本地的開發代碼沒有影響。

默認狀況下,git fetch取回全部分支(branch)的更新。若是隻想取回特定分支的更新,能夠指定分支名。

$ git fetch <遠程主機名> <分支名>

好比,取回origin主機的master分支。

$ git fetch origin master

所取回的更新,在本地主機上要用"遠程主機名/分支名"的形式讀取。好比origin主機的master,就要用origin/master讀取。

git branch命令的-r選項,能夠用來查看遠程分支,-a選項查看全部分支。

$ git branch -r
origin/master

$ git branch -a
* master
  remotes/origin/master

上面命令表示,本地主機的當前分支是master,遠程分支是origin/master

取回遠程主機的更新之後,能夠在它的基礎上,使用git checkout命令建立一個新的分支。

$ git checkout -b newBrach origin/master

上面命令表示,在origin/master的基礎上,建立一個新分支。

此外,也可使用git merge命令或者git rebase命令,在本地分支上合併遠程分支。

$ git merge origin/master
# 或者
$ git rebase origin/master

上面命令表示在當前分支上,合併origin/master

git pull

git pull命令的做用是,取回遠程主機某個分支的更新,再與本地的指定分支合併。它的完整格式稍稍有點複雜。

$ git pull <遠程主機名> <遠程分支名>:<本地分支名>

好比,取回origin主機的next分支,與本地的master分支合併,須要寫成下面這樣。

$ git pull origin next:master

若是遠程分支是與當前分支合併,則冒號後面的部分能夠省略。

$ git pull origin next

上面命令表示,取回origin/next分支,再與當前分支合併。實質上,這等同於先作git fetch,再作git merge

$ git fetch origin
$ git merge origin/next

在某些場合,Git會自動在本地分支與遠程分支之間,創建一種追蹤關係(tracking)。好比,在git clone的時候,全部本地分支默認與遠程主機的同名分支,創建追蹤關係,也就是說,本地的master分支自動"追蹤"origin/master分支。

Git也容許手動創建追蹤關係。

git branch --set-upstream master origin/next

上面命令指定master分支追蹤origin/next分支。

若是當前分支與遠程分支存在追蹤關係,git pull就能夠省略遠程分支名。

$ git pull origin

上面命令表示,本地的當前分支自動與對應的origin主機"追蹤分支"(remote-tracking branch)進行合併。

若是當前分支只有一個追蹤分支,連遠程主機名均可以省略。

$ git pull

上面命令表示,當前分支自動與惟一一個追蹤分支進行合併。

若是合併須要採用rebase模式,可使用--rebase選項。

$ git pull --rebase <遠程主機名> <遠程分支名>:<本地分支名>

若是遠程主機刪除了某個分支,默認狀況下,git pull 不會在拉取遠程分支的時候,刪除對應的本地分支。這是爲了防止,因爲其餘人操做了遠程主機,致使git pull不知不覺刪除了本地分支。

可是,你能夠改變這個行爲,加上參數 -p 就會在本地刪除遠程已經刪除的分支。

$ git pull -p
# 等同於下面的命令
$ git fetch --prune origin 
$ git fetch -p

git push

git push命令用於將本地分支的更新,推送到遠程主機。它的格式與git pull命令相仿。

$ git push <遠程主機名> <本地分支名>:<遠程分支名>

注意,分支推送順序的寫法是<來源地>:<目的地>,因此git pull是<遠程分支>:<本地分支>,而git push是<本地分支>:<遠程分支>。

若是省略遠程分支名,則表示將本地分支推送與之存在"追蹤關係"的遠程分支(一般二者同名),若是該遠程分支不存在,則會被新建。

$ git push origin master

上面命令表示,將本地的master分支推送到origin主機的master分支。若是後者不存在,則會被新建。

若是省略本地分支名,則表示刪除指定的遠程分支,由於這等同於推送一個空的本地分支到遠程分支。

$ git push origin :master
# 等同於
$ git push origin --delete master

上面命令表示刪除origin主機的master分支。

若是當前分支與遠程分支之間存在追蹤關係,則本地分支和遠程分支均可以省略。

$ git push origin

上面命令表示,將當前分支推送到origin主機的對應分支。

若是當前分支只有一個追蹤分支,那麼主機名均可以省略。

$ git push

若是當前分支與多個主機存在追蹤關係,則可使用-u選項指定一個默認主機,這樣後面就能夠不加任何參數使用git push

$ git push -u origin master

上面命令將本地的master分支推送到origin主機,同時指定origin爲默認主機,後面就能夠不加任何參數使用git push了。

不帶任何參數的git push,默認只推送當前分支,這叫作simple方式。此外,還有一種matching方式,會推送全部有對應的遠程分支的本地分支。Git 2.0版本以前,默認採用matching方法,如今改成默認採用simple方式。若是要修改這個設置,能夠採用git config命令。

$ git config --global push.default matching
# 或者
$ git config --global push.default simple

還有一種狀況,就是無論是否存在對應的遠程分支,將本地的全部分支都推送到遠程主機,這時須要使用--all選項。

$ git push --all origin

上面命令表示,將全部本地分支都推送到origin主機。

若是遠程主機的版本比本地版本更新,推送時Git會報錯,要求先在本地作git pull合併差別,而後再推送到遠程主機。這時,若是你必定要推送,可使用--force選項。

$ git push --force origin

上面命令使用--force選項,結果致使遠程主機上更新的版本被覆蓋。除非你很肯定要這樣作,不然應該儘可能避免使用--force選項。

最後,git push不會推送標籤(tag),除非使用--tags選項。

$ git push origin --tags
相關文章
相關標籤/搜索