1. 程式人生 > >Git 使用指南(標準版)

Git 使用指南(標準版)

告訴 不想 怎麽辦 創建 目前 img 上推 你們 push

0. 說明

  學習和理解和轉載於 Git使用教程,最詳細,最傻瓜,最淺顯,真正手把手教
  相當於過了一遍   Git 分支在線練習

1. 介紹

1.1 Git 是什麽

  Git 是分布式版本控制系統   工作原理/流程如下圖所示

技術分享圖片

  1. Workspace:工作區   2. Index / Stage:暫存區   3. Repository:倉庫區(或本地倉庫)   4. Remote:遠程倉庫

1.2 SVN 與 Git 的最主要的區別

  SVN 是集中式版本控制系統,版本庫是集中放在中央服務器的,而幹活的時候,用的都是自己的電腦,所以首先要從中央服務器哪裏得到最新的版本,然後幹活,幹完後,需要把自己做完的活推送到中央服務器。集中式版本控制系統是必須聯網才能工作,如果在局域網還可以,帶寬夠大,速度夠快,如果在互聯網下,如果網速慢的話,就納悶了。
  Git 是分布式版本控制系統,那麽它就沒有中央服務器的,每個人的電腦就是一個完整的版本庫,這樣,工作的時候就不需要聯網了,因為版本都是在自己的電腦上。既然每個人的電腦都有一個完整的版本庫,那多個人如何協作呢?比如說自己在電腦上改了文件A,其他人也在電腦上改了文件A,這時,你們兩之間只需把各自的修改推送給對方,就可以互相看到對方的修改了。

2. 安裝 Git

2.1 在 Windows 上安裝 Git

  Git 下載   在開始菜單裏找到 Git -> Git Bash ,名稱和郵箱是 Github 上的
# 指定 Github 的用戶名
git config 
-- global user.name "username" # 指定 Github 的郵箱 git config -- global user.email "[email protected]"

  因為Git是分布式版本控制系統,所以需要填寫用戶名和郵箱作為一個標識。   註意:git config --global 參數,有了這個參數,表示你這臺機器上所有的 Git 倉庫都會使用這個配置,當然你也可以對某個倉庫指定的不同的用戶名和郵箱。

2.2 在 Centos 下安裝 Git

sudo yum install git

3. 操作

3.1 創建版本庫

  版本庫又名倉庫,英文名 repository ,你可以簡單的理解一個目錄,這個目錄裏面的所有文件都可以被 Git 管理起來,每個文件的修改,刪除,Git都能跟蹤,以便任何時刻都可以追蹤歷史,或者在將來某個時刻還可以將文件”還原”。   新建一個文件夾 test ,在命令行下進入該目錄對其進行初始化操作
# 將當前目錄變成 git 可以管理的倉庫
git init

3.2 添加文件到版本庫

  在倉庫中新建一個文件 readme.md ,添加相應的內容,然後進行如下操作
# 1. 將 readme.md 添加到暫存區
git add readme.md
 

# 2. 將暫存區的內容提交到本地倉庫, xxx 是提交的註釋
git commit -m "xxx"
 

# 3. 查看是否有文件未提交
git status
 

# 4. 修改 readme.md 文件內容,通過git status可以得到文件已經修改過
# 通過以下命令查看修改內容
 

git diff readme.md
 

# 5. 修改過後重復 12 步驟
 

# 6. 第一次提交到遠程
git push -u origin master

3.3 版本回退

  為 readme.md 添加一行內容然後添加到本地倉庫

  查看歷史提交記錄

# 1. 查看歷史
git log

# 2. 單行顯示提交歷史註釋
git log –pretty=oneline

  版本回退

# 1. 回退到上一個版本
git reset --hard HEAD^
 

# 2. 回退到上2個版本
git reset --hard HEAD^^
 

# 3. 回退到上100個版本
git reset --hard HEAD~100

  回退到之前的版本之後又想恢復到最新的版本

# 1. 獲取版本號
git reflog

# 2. 恢復指定版本的數據,6fcfc89 為要恢復版本的版本號
git reset --hard 6fcfc89

3.4 工作區與暫存區的區別

  區別

  在電腦上看到的目錄,比如目錄下test裏的文件(.git隱藏目錄版本庫除外)。或者以後需要再新建的目錄文件等等都屬於工作區範疇。   版本庫(Repository):工作區有一個隱藏目錄.git,這個不屬於工作區,這是版本庫。其中版本庫裏面存了很多東西,其中最重要的就是 stage(暫存區),還有Git為我們自動創建了第一個分支 master ,以及指向 master 的一個指針HEAD。   使用Git提交文件到版本庫有兩步:   1. 是使用 git add 把文件添加進去,實際上就是把文件添加到暫存區。   2. 使用 git commit 提交更改,實際上就是把暫存區的所有內容提交到當前分支上。   在多次添加文件之後可以通過 git commit 一次性提交

3.5 撤銷修改和刪除文件

  撤銷修改

  對文件進行修改之後不滿意想回到原來的版本(但記不清該刪什麽,又想不通過版本回退)
# 1. 丟棄工作區的修改,如果加入到暫存區就不能撤銷修改了
git checkout -- readme.md
  (PS: 命令 git checkout -- readme.md 中的 -- 很重要,如果沒有 -- 的話,那麽命令變成創建分支了)

  刪除文件
# 1. 在工作區刪除文件
# 之後有兩個選擇(1. commit 2. 從版本庫中恢復被刪掉的文件)
rm readme.md
 

# 2. 未 commit 之前 從版本庫中恢復被刪掉的文件
git checkout -- readme.md

3.6 遠程倉庫

3.6.1 配置 GitHub

  登陸註冊 GitHub

  本地 Git倉庫 和 GitHub倉庫 之間的傳輸是通過 SSH 加密的,所以需要如下操作

# 1. 創建 SSH Key
# 在用戶主目錄下,看看有沒有.ssh目錄,如果有,再看看這個目錄下有沒有
# id_rsa和id_rsa.pub這兩個文件,如果有的話,直接跳過此如下命令,
# 如果沒有的話,打開命令行,輸入如下命令
ssh-keygen -t rsa -C "Github的註冊郵箱地址"
 

# 2.
# 登錄 GitHub,打開 "Settings" 中的 SSH Keys 頁面
# 然後點擊 "Add SSH Key" ,填上任意 title
# 在 Key 文本框裏粘貼 id_rsa.pub 文件的內容。
  (PS: id_rsa 是私鑰,不能泄露出去,id_rsa.pub 是公鑰,可以放心地告訴任何人)

3.6.2 添加遠程倉庫

  現在的情景是:我們已經在本地創建了一個 Git倉庫 後,又想在 GitHub 創建一個 Git倉庫,並且希望這兩個倉庫進行遠程同步,這樣 GitHub 的倉庫可以作為備份,又可以其他人通過該倉庫來協作

# 1. New repository
 

# 2. 輸入 Repository name (與本地倉庫同名)
testgit
# 3. Create repository
 

# 4. 將一個已有的本地倉庫與遠程倉庫關聯
git remote add origin https://github.com/username/testgit.git
 

# 5. 將本地倉庫 master 分支的內容推送到遠程倉庫中
git pish -u origin master
 

# 6. 第二次及之後上傳項目
git push origin master
 

# 說明 由於遠程庫是空的,我們第一次推送 master 分支時,加上了 –u 參數
# Git 不但會把本地的 master 分支內容推送的遠程新的 master 分支
# 還會把本地的 master 分支和遠程的 master 分支關聯起來

3.6.3 從遠程倉庫克隆項目到本地

git clone https://github.com/username/testgit

3.7 創建與合並分支

3.7.1 分支說明

  每次提交,Git 都把它們串成一條時間線,這條時間線就是一個分支。截止到目前,只有一條時間線,在 Git 裏,這個分支叫主分支,即 master 分支。HEAD 嚴格來說不是指向提交,而是指向 master ,master 才是指向提交的,所以,HEAD 指向的就是當前分支。

3.7.2 Demo

  創建 dev 分支,並切換到該分支
# 1. 創建 dev 分支並切換分支
git checkout -b dev
 
# 2. 查看當前的分支,列出所有的分支,當前分支前面會添加一個星號
git branch

技術分享圖片

  git checkout 命令加上 –b參數表示創建並切換,相當於如下2條命令

# 創建分支
git branch dev
 
# 切換分支
git checkout dev

  新建一個文件 test_branch_dev.txt ,在裏面添加一些內容,然後做以下操作,驗證切換分支之後前一個分支的操作能否被查看

技術分享圖片

3.7.3 合並分支

# 在 master 分支上合並 dev 分支的內容
git merge dev

# 繼續查看 test_branch_dev.txt 的內容
cat test_branch_dev.txt

技術分享圖片

註意到上面的 Fast-forward 信息,Git 告訴我們,這次合並是“快進模式”,也就是直接把 master 指向 dev 的當前提交,所以合並速度非常快。

3.7.4 刪除分支
# 刪除 dev 分支
git branch -d dev

# 查看分支命令
git branch

技術分享圖片

3.7.5 分支操作命令合集

# 查看分支
git branch

# 創建分支
git branch name

# 切換分支
git checkout name

# 創建+切換分支
git checkout –b name

# 合並某分支到當前分支
git merge name

# 刪除分支
git branch –d name

3.7.6 分支沖突

# 新建並切換分支
git checkout –b fenzhi1

# 查看 test_branch_dev.txt 的內容
cat test_branch_dev.txt

# 添加內容後繼續查看 test_branch_dev.txt 的內容
cat test_branch_dev.txt

# 添加到暫存區
git add test_branch_dev.txt

# 提交到本地倉庫
git commit -m "add fenzhi1"

技術分享圖片

# 切換到 master 分支
git checkout master

# 查看 test_branch_dev.txt 的內容
cat test_branch_dev.txt

# 添加內容後繼續查看 test_branch_dev.txt 的內容
cat test_branch_dev.txt

# 添加到暫存區
git add test_branch_dev.txt

# 提交到本地倉庫
git commit -m "add master"

技術分享圖片

# 在 master 分支上合並 branch1
git merge fenzhi1

# 查看狀態
git status

# 查看 test_branch_dev.txt 的內容
cat test_branch_dev.txt

技術分享圖片

技術分享圖片

  Git用<<<<<<<,=======,>>>>>>>標記出不同分支的內容,其中<<<HEAD是指主分支修改的內容,>>>>>fenzhi1 是指fenzhi1上修改的內容

# 解決分支沖突,將文件test_branch_dev.txt的內容修改成主幹代碼的
# 查看 test_branch_dev.txt 的內容
cat test_branch_dev.txt

技術分享圖片

# 查看分支合並的情況
git log

技術分享圖片

3.7.7 分支管理策略

  通常合並分支時,git 一般使用 `Fast forward` 模式,在這種模式下,刪除分支後,會丟掉分支信息,現在我們來使用帶參數 `–no-ff` 來禁用 `Fast forward` 模式   演示如下

技術分享圖片

  分支策略:首先 master主分支 應該是非常穩定的,也就是用來發布新版本,一般情況下不允許在上面幹活,幹活一般情況下在新建的 dev分支 上幹活,幹完後,比如上要發布,或者說 dev分支 代碼穩定後可以合並到 主分支master 上來。

3.8 Bug 分支

  在開發中,會經常碰到bug問題,那麽有了bug就需要修復,在Git中,分支是很強大的,每個bug都可以通過一個臨時分支來修復,修復完成後,合並分支,然後將臨時的分支刪除掉。   比如我在開發中接到一個404 bug時候,我們可以創建一個404分支來修復它,但是,當前的dev分支上的工作還沒有提交。比如如下:

技術分享圖片

  並不是我不想提交,而是工作進行到一半時候,我們還無法提交,比如我這個分支bug要2天完成,但是我issue-404 bug需要5個小時內完成。怎麽辦呢?還好,Git還提供了一個stash功能,可以把當前工作現場 ”隱藏起來”,等以後恢復現場後繼續工作。如下:

技術分享圖片

  所以現在我可以通過創建issue-404分支來修復bug了。   首先我們要確定在那個分支上修復bug,比如我現在是在主分支master上來修復的,現在我要在master分支上創建一個臨時分支,演示如下:

技術分享圖片

  現在,我們回到dev分支上幹活了

技術分享圖片

  工作區是幹凈的,那麽我們工作現場去哪裏呢?我們可以使用命令 git stash list來查看下。如下:

技術分享圖片

  工作現場還在,Git把stash內容存在某個地方了,但是需要恢復一下,可以使用如下2個方法:   1.git stash apply恢復,恢復後,stash內容並不刪除,你需要使用命令git stash drop來刪除。   2.另一種方式是使用git stash pop,恢復的同時把stash內容也刪除了。   演示如下

技術分享圖片

3.9 多人協作

  當你從遠程庫克隆時候,實際上Git自動把本地的master分支和遠程的master分支對應起來了,並且遠程庫的默認名稱是origin。   要查看遠程庫的信息 使用 git remote   要查看遠程庫的詳細信息 使用 git remote –v   如下演示:

技術分享圖片

3.9.1 推送分支

  推送分支就是把該分支上所有本地提交到遠程庫中,推送時,要指定本地分支,這樣,Git就會把該分支推送到遠程庫對應的遠程分支上

# 推送到 master分支 git push origin master # 推送到 dev分支 git push origin dev ``` bash ```

``` bash ```

那麽一般情況下,那些分支要推送呢?

master分支 是主分支,因此要時刻與遠程同步。

一些 修復bug分支 不需要推送到遠程去,可以先合並到主分支上,然後把主分支master推送到遠程去。

#### 抓取分支

多人協作時,大家都會往 master分支 上推送各自的修改。現在我們可以模擬另外一個同事,可以在另一臺電腦上(註意要把SSH key添加到github上)或者同一臺電腦上另外一個目錄克隆,新建一個目錄名字叫testgit2

但是我首先要把dev分支也要推送到遠程去,如下

![Git_branch18.jpg](pic/Git_branch18.jpg)

技術分享圖片

接著進入testgit2目錄,進行克隆遠程的庫到本地來,如下

![Git_branch19.jpg](pic/Git_branch19.jpg)

技術分享圖片

現在目錄下生成有如下所示

![Git_branch20.jpg](pic/Git_branch20.jpg)

技術分享圖片

現在我們的小夥伴要在 dev分支 上做開發,就必須把遠程的origin的 dev分支 到本地來,於是可以使用命令創建本地dev分支:`git checkout –b dev origin/dev`

現在小夥伴們就可以在 dev分支 上做開發了,開發完成後把 dev分支 推送到遠程庫時。

如下

![Git_branch21.jpg](pic/Git_branch21.jpg)

技術分享圖片

小夥伴們已經向origin/dev分支上推送了提交,而我在我的目錄文件下也對同樣的文件同個地方作了修改,也試圖推送到遠程庫時,如下

![Git_branch22.jpg](pic/Git_branch22.jpg)

技術分享圖片

由上面可知:推送失敗,因為我的小夥伴最新提交的和我試圖推送的有沖突,解決的辦法也很簡單,上面已經提示我們,先用git pull把最新的提交從origin/dev抓下來,然後在本地合並,解決沖突,再推送。

![Git_branch23.jpg](pic/Git_branch23.jpg)

技術分享圖片

git pull 也失敗了,原因是沒有指定 本地dev分支 與 遠程origin/dev分支 的鏈接,根據提示,設置dev和origin/dev的鏈接:如下

![Git_branch24.jpg](pic/Git_branch24.jpg)

技術分享圖片

這回git pull成功,但是合並有沖突,需要手動解決,解決的方法和分支管理中的 解決沖突完全一樣。解決後,提交,再push:

我們可以先來看看readme.txt內容了

![Git_branch25.jpg](pic/Git_branch25.jpg)

技術分享圖片

現在手動已經解決完了,我接在需要再提交,再push到遠程庫裏面去。如下所示

![Git_branch25.jpg](pic/Git_branch26.jpg)

技術分享圖片

因此:多人協作工作模式一般是這樣的:

首先,可以試圖用 `git push origin branch-name` 推送自己的修改.

如果推送失敗,則因為遠程分支比你的本地更新早,需要先用 `git pull` 試圖合並。

如果合並有沖突,則需要解決沖突,並在本地提交。再用 `git push origin branch-name` 推送。





## 阮老師整理的部分命令

[阮老師整理的部分命令](http://www.ruanyifeng.com/blog/2015/12/git-cheat-sheet.html)

### 新建代碼庫

``` bash # 在當前目錄新建一個Git代碼庫 $ git init

# 新建一個目錄,將其初始化為Git代碼庫 $ git init [project-name]

# 下載一個項目和它的整個代碼歷史 $ git clone [url] ```

### 配置

Git 的設置文件為 `.gitconfig` ,它可以在用戶主目錄下(全局配置),也可以在項目目錄下(項目配置)

``` bash # 顯示當前的Git配置 $ git config --list

# 編輯Git配置文件 $ git config -e [--global]

# 設置提交代碼時的用戶信息 $ git config [--global] user.name "[name]" $ git config [--global] user.email "[email address]" ```

### 增加/刪除文件

``` bash # 添加指定文件到暫存區 $ git add [file1] [file2] ...

# 添加指定目錄到暫存區,包括子目錄 $ git add [dir]

# 添加當前目錄的所有文件到暫存區 $ git add .

# 添加每個變化前,都會要求確認 # 對於同一個文件的多處變化,可以實現分次提交 $ git add -p

# 刪除工作區文件,並且將這次刪除放入暫存區 $ git rm [file1] [file2] ...

# 停止追蹤指定文件,但該文件會保留在工作區 $ git rm --cached [file]

# 改名文件,並且將這個改名放入暫存區 $ git mv [file-original] [file-renamed] ```

### 代碼提交 ``` bash # 提交暫存區到倉庫區 $ git commit -m [message]

# 提交暫存區的指定文件到倉庫區 $ git commit [file1] [file2] ... -m [message]

# 提交工作區自上次commit之後的變化,直接到倉庫區 $ git commit -a

# 提交時顯示所有diff信息 $ git commit -v

# 使用一次新的commit,替代上一次提交 # 如果代碼沒有任何新變化,則用來改寫上一次commit的提交信息 $ git commit --amend -m [message]

# 重做上一次commit,並包括指定文件的新變化 $ git commit --amend [file1] [file2] ... ```

### 分支

``` bash # 列出所有本地分支 $ git branch

# 列出所有遠程分支 $ git branch -r

# 列出所有本地分支和遠程分支 $ git branch -a

# 新建一個分支,但依然停留在當前分支 $ git branch [branch-name]

# 新建一個分支,並切換到該分支 $ git checkout -b [branch]

# 新建一個分支,指向指定commit $ git branch [branch] [commit]

# 新建一個分支,與指定的遠程分支建立追蹤關系 $ git branch --track [branch] [remote-branch]

# 切換到指定分支,並更新工作區 $ git checkout [branch-name]

# 切換到上一個分支 $ git checkout -

# 建立追蹤關系,在現有分支與指定的遠程分支之間 $ git branch --set-upstream [branch] [remote-branch]

# 合並指定分支到當前分支 $ git merge [branch]

# 選擇一個commit,合並進當前分支 $ git cherry-pick [commit]

# 刪除分支 $ git branch -d [branch-name]

# 刪除遠程分支 $ git push origin --delete [branch-name] $ git branch -dr [remote/branch] ```

### 標簽

``` bash # 列出所有tag $ git tag

# 新建一個tag在當前commit $ git tag [tag]

# 新建一個tag在指定commit $ git tag [tag] [commit]

# 刪除本地tag $ git tag -d [tag]

# 刪除遠程tag $ git push origin :refs/tags/[tagName]

# 查看tag信息 $ git show [tag]

# 提交指定tag $ git push [remote] [tag]

# 提交所有tag $ git push [remote] --tags

# 新建一個分支,指向某個tag $ git checkout -b [branch] [tag] ```

### 查看信息

``` bash # 顯示有變更的文件 $ git status

# 顯示當前分支的版本歷史 $ git log

# 顯示commit歷史,以及每次commit發生變更的文件 $ git log --stat

# 搜索提交歷史,根據關鍵詞 $ git log -S [keyword]

# 顯示某個commit之後的所有變動,每個commit占據一行 $ git log [tag] HEAD --pretty=format:%s

# 顯示某個commit之後的所有變動,其"提交說明"必須符合搜索條件 $ git log [tag] HEAD --grep feature

# 顯示某個文件的版本歷史,包括文件改名 $ git log --follow [file] $ git whatchanged [file]

# 顯示指定文件相關的每一次diff $ git log -p [file]

# 顯示過去5次提交 $ git log -5 --pretty --oneline

# 顯示所有提交過的用戶,按提交次數排序 $ git shortlog -sn

# 顯示指定文件是什麽人在什麽時間修改過 $ git blame [file]

# 顯示暫存區和工作區的差異 $ git diff

# 顯示暫存區和上一個commit的差異 $ git diff --cached [file]

# 顯示工作區與當前分支最新commit之間的差異 $ git diff HEAD

# 顯示兩次提交之間的差異 $ git diff [first-branch]...[second-branch]

# 顯示今天你寫了多少行代碼 $ git diff --shortstat "@{0 day ago}"

# 顯示某次提交的元數據和內容變化 $ git show [commit]

# 顯示某次提交發生變化的文件 $ git show --name-only [commit]

# 顯示某次提交時,某個文件的內容 $ git show [commit]:[filename]

# 顯示當前分支的最近幾次提交 $ git reflog ```

### 遠程同步

``` bash # 下載遠程倉庫的所有變動 $ git fetch [remote]

# 顯示所有遠程倉庫 $ git remote -v

# 顯示某個遠程倉庫的信息 $ git remote show [remote]

# 增加一個新的遠程倉庫,並命名 $ git remote add [shortname] [url]

# 取回遠程倉庫的變化,並與本地分支合並 $ git pull [remote] [branch]

# 上傳本地指定分支到遠程倉庫 $ git push [remote] [branch]

# 強行推送當前分支到遠程倉庫,即使有沖突 $ git push [remote] --force

# 推送所有分支到遠程倉庫 $ git push [remote] --all ```

### 撤銷

``` bash # 恢復暫存區的指定文件到工作區 $ git checkout [file]

# 恢復某個commit的指定文件到暫存區和工作區 $ git checkout [commit] [file]

# 恢復暫存區的所有文件到工作區 $ git checkout .

# 重置暫存區的指定文件,與上一次commit保持一致,但工作區不變 $ git reset [file]

# 重置暫存區與工作區,與上一次commit保持一致 $ git reset --hard

# 重置當前分支的指針為指定commit,同時重置暫存區,但工作區不變 $ git reset [commit]

# 重置當前分支的HEAD為指定commit,同時重置暫存區和工作區,與指定commit一致 $ git reset --hard [commit]

# 重置當前HEAD為指定commit,但保持暫存區和工作區不變 $ git reset --keep [commit]

# 新建一個commit,用來撤銷指定commit # 後者的所有變化都將被前者抵消,並且應用到當前分支 $ git revert [commit]

# 暫時將未提交的變化移除,稍後再移入 $ git stash $ git stash pop ```

Git 使用指南(標準版)