小豬的Git使用總結
目錄
概述:
接觸Git也些年頭了,對於Git的使用也算是略有心得,想着
出於自己日後回顧,也便於他人查閱學習的目的,遂有此文,
相信看完此文你的Git使用會更進一步,謝謝~
PS:有些童鞋曾私信問我爲什麼有圖形化的Git工具還要學
命令行,原因挺多的,我覺得最主要的原因有三點:
- 1.減少跨平臺使用Git成本,不用另外花時間去熟悉各種工具;
- 2.知道原理,出問題的時候不會一臉懵逼;
- 3.裝逼,敲起來命令噼裏啪啦,不知道還以爲你真的是大神;
在線版(排版更佳,優先更新):https://www.zybuluo.com/coder-pig/note/581320
本文不收取任何費用,歡迎轉載,但請註明原文出處!
禁止將本文用於商業用途,想了解更多內容可見:
http://blog.csdn.net/coder_pig
如果本文對你學習Git有一定幫助,不妨小額打賞下小豬,
你的鼓勵是我不斷寫博客的動力, 萬分感謝~
微信: 支付寶:
如有什麼疑問歡迎加羣:421858269 反饋,謝謝~
安裝配置與文檔
1.下載安裝
- Windows系統:到 Git For Windows 或 git-for-windows.github.io下載,傻瓜式下一步。
- Linux系統:到 Download for Linux and Unix 下載,如果是Ubuntu的話,直接Terminal鍵入:
sudo apt-get install git 安裝。 - Mac系統:到 Installing on Mac 下載,不過新系統貌似默認已經帶有Git了,另外如果安裝了
Homebrew的話可以直接命令行鍵入:brew install git 進行安裝。
2.文檔教程相關
- Pro Git(官方):https://git-scm.com/book/zh/v2
- Pro Git中文版(oschina):http://git.oschina.net/progit/index.html
- 廖雪峯的Git教程:
http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000 - 猴子都看得懂的Git入門:http://www.backlogtool.com/git-guide/cn/
- Git Community Book 中文版:http://gitbook.liuhui998.com/index.html
- 沉浸式學Git:http://igit.linuxtoy.org/contents.html
- .gitignore 文件模板:https://github.com/github/gitignore
- git log –pretty 輸出格式定製:https://git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-History
- Git Cheat Sheet: Useful Commands, Tips and Tricks:
https://sentheon.com/blog/git-cheat-sheet.html
概念
1.Git的四個組成部分
2.文件的幾個狀態
按大類劃分,分爲兩種狀態:Tracked(已跟蹤)和Untracked(未跟蹤),
依據是:該文件是否已加入版本控制?
流程簡述:
假設某個項目已加入版本控制系統
- 1.新建一個文件,該文件處於 Untracked 狀態;
- 2.通過git add命令添加到緩存區,此時文件處於Tracked狀態又或者說
此時這個文件已經被版本控制系統所跟蹤,而且他處於Staged(暫存)狀態;- 3.通過git commit命令把暫存區的文件提交提交到本地倉庫,此時文件
處於Unmodified(未修改)狀態;- 4.此時如果去編輯這個文件,文件又會變成Modified(修改)狀態;
3.Git與SVN版本版本控制存儲差異
Git關心的是:文件整體是否發生變化,而SVN關心的是:文件內容的具體差異!
SVN每次提交記錄的是:哪些文件進行了修改,以及修改了哪些行的哪些內容
如圖:版本2中記錄的是文件A和C的變化,而版本3中記錄文件C的變化,以此類推;
而Git中,並不保存這些前後變化的差異數據,而是保證整個緩存區中的所有文件,
又叫快照,有變化的文件保存,沒變化的文件不保存,而是對上一次的保存的快照
做一個鏈接!因爲這種不同的保存方式,Git切換分支的速度比SVN快很多!
4.每次Commit時倉庫中的數據結構
分爲四個對象:
blob對象:存放文件數據;
tree對象:目錄,內容爲blob對象的指針或其他tree對象的指針
commit對象:快照,包含指向前一次提交對象的指針,commit相關的信
通過索引找到文件快照。
tag對象:一種特殊的commit對象,一般對某次重要的commit加TAG,以示重要(方便找)
本地操作命令
1.相關配置【git config】
區分global 和 local,前者代表 全局設置,就是設置了在整個系統中,
所有的帶Git版本管理的項目都是這樣的配置;後者代表 本地設置
即在某個項目中獨立的設置,後者優先級高於前者。比如全局設置
的用戶名是”Coder-pig”,本地設置的是”Jay”,commit的時候author
就是Jay而不是Coder-pig。除了通過命令行修改,還可以直接修改
對應文件:
全局配置文件:etc/gitconfig (Mac下是隱藏文件,用戶/.gitconfig)
本地配置文件:當前倉庫/.git/config
# 安裝完Git後第一件要做的事,設置用戶信息(global可換成local在單獨項目生效):
git config --global user.name "用戶名" # 設置用戶名
git config --global user.email "用戶郵箱" #設置郵箱
git config --global user.name # 查看用戶名是否配置成功
git config --global user.email # 查看郵箱是否配置
# 其他查看配置相關
git config --global --list # 查看全局設置相關參數列表
git config --local --list # 查看本地設置相關參數列表
git config --system --list # 查看系統配置參數列表
git config --list # 查看所有Git的配置(全局+本地+系統)
2.獲取幫助【git help】
git help 命令 # 如:git help init
3.創建本地倉庫【git init】
git init 倉庫名 # 創建一個新的帶Git倉庫的項目
git init # 爲已存在的項目生成一個Git倉庫
4.添加文件到暫存區/文件跟蹤標記【git add】
可以使用git add 文件名,將工作空間的文件添加到暫存區,或批量添加文件
git add 文件名 # 將工作區的某個文件添加到暫存區
git add -u # 添加所有被tracked文件中被修改或刪除的文件信息到暫存區,不處理untracked的文件
git add -A # 添加所有被tracked文件中被修改或刪除的文件信息到暫存區,包括untracked的文件
git add . # 將當前工作區的所有文件都加入暫存區
git add -i # 進入交互界面模式,按需添加文件到緩存區
附:交互界面模式示例
上圖流程:
1.先在GitForTest的文件夾裏創建了兩個文件
2.鍵入git add -i,進入後,鍵入4,選擇添加untracked的文件
3.他給我們列出了untracked的文件,然後我們根據序號來添加文件
4.輸入?會彈出相關提示,然後直接回車,結束選擇!
5.然後再次輸入git add -i,輸入4,可以看到已不存在untacked的文件了!
5.讓Git不Tracked特定文件【.gitignore文件配置】
將未tracked的文件添加到緩存區後,Git就會開始跟蹤這個文件了!
對於一些比如:自動生成的文件,日誌,臨時編譯文件等,就
沒必要進行跟蹤了,這個時候可以編寫.gitignore文件,在裏面
把不需要跟蹤的文件或文件夾都寫上,git就不會對這些文件進行跟蹤!
另外.gitignore文件與.git文件夾在同級目錄下!
如果不想自己寫,可以直接到:https://github.com/github/gitignore 複製粘貼!
也可以自行編寫,支持簡化了的正則表達式(規範與示例模板摘自:Git王者超神之路)
- * : 匹配零個或多個任意字符
- [abc]:只匹配括號內中的任意一個字符
- [0-9]:- 代表範圍,匹配0-9之間的任何字符
- ?:匹配任意一個字符
- *:匹配任意的中間目錄,例如a/*/z可以匹配:a/z,a/b/z,a/b/c/z等
示例模板:
# 忽略所有以 .c結尾的文件
*.c
# 但是 stream.c 會被git追蹤
!stream.c
# 只忽略當前文件夾下的TODO文件, 不包括其他文件夾下的TODO例如: subdir/TODO
/TODO
# 忽略所有在build文件夾下的文件
build/
# 忽略 doc/notes.txt, 但不包括多層下.txt例如: doc/server/arch.txt
doc/*.txt
# 忽略所有在doc目錄下的.pdf文件
doc/**/*.pdf
!!!特別要注意一點!!!:
配置.gitignore只對那些沒有添加到版本控制系統的文件生效(未Tracked的文件)!
舉個例子:
有A,B兩個文件,你先把他兩個add了,然後在.gitignore文件中
配置了不跟蹤這兩個文件,但是你會發現根本不會生效。
git add A
git add B
# 配置不跟蹤A和B
git add .gitignore
所以,最好的做法就是在項目剛開始的時候,先添加.gitignore文件。
當然,即使是發生了,還是有解決方法的,可以鍵入下述命令清除標
記狀態,然後先添加.gitignore,再添加文件即可:
git rm -r --cached . # 清除版本控制標記,.代表所有文件,也可指定具體文件
還有,如果你用的是IDEA的編輯器的話,可以下一個.ignore的插件,可以手動
直接勾選不需要跟蹤的文件。
6.將暫存區內容提交到本地倉庫【git commit】
git commit -m "提交說明" # 將暫存區內容提交到本地倉庫
git commit -a -m "提交說明" # 跳過緩存區操作,直接把工作區內容提交到本地倉庫
如果不加-m “提交說明”,git會讓用你讓默認編輯器(如vi)來編寫提交說明,
可能有些朋友用不慣vi,要麼別漏掉-m “提交說明”,要麼自己設置編譯器:
git config --global core.edit 喜歡的編輯器
除此之外,有時可能需要修改上次提交的內容,比如修改提交說明,或者修改文件等:
# 合併暫存區和最近的一次commit,生成新的commit並替換掉老的
# 如果緩存區沒內容,利用amend可以修改上次commit的提交說明
# 注:因爲amend後生成的commit是一個全新的commit,舊的會被
# 刪除,所以別在公共的commit上使用amend!切記!!!
git commit --amend
git commit --amend --no-edit # 沿用上次commit的提交說明
7.查看工作區與緩存區的狀態【git status】
git status # 查看工作區與暫存區的當前情況
git status -s # 讓結果以更簡短的形式輸出
8.差異對比(內容變化)【git diff】
git diff # 工作區與緩存區的差異
git diff 分支名 #工作區與某分支的差異,遠程分支這樣寫:remotes/origin/分支名
git diff HEAD # 工作區與HEAD指針指向的內容差異
git diff 提交id 文件路徑 # 工作區某文件當前版本與歷史版本的差異
git diff --stage # 工作區文件與上次提交的差異(1.6 版本前用 --cached)
git diff 版本TAG # 查看從某個版本後都改動內容
git diff 分支A 分支B # 比較從分支A和分支B的差異(也支持比較兩個TAG)
git diff 分支A...分支B # 比較兩分支在分開後各自的改動
# 另外:如果只想統計哪些文件被改動,多少行被改動,可以添加 --stat 參數
9.查看歷史提交記錄【git log】
git log # 查看所有commit記錄(SHA-A校驗和,作者名稱,郵箱,提交時間,提交說明)
git log -p -次數 # 查看最近多少次的提交記錄
git log --stat # 簡略顯示每次提交的內容更改
git log --name-only # 僅顯示已修改的文件清單
git log --name-status # 顯示新增,修改,刪除的文件清單
git log --oneline # 讓提交記錄以精簡的一行輸出
git log –graph –all --online # 圖形展示分支的合併歷史
git log --author=作者 # 查詢作者的提交記錄(和grep同時使用要加一個--all--match參數)
git log --grep=過濾信息 # 列出提交信息中包含過濾信息的提交記錄
git log -S查詢內容 # 和--grep類似,S和查詢內容間沒有空格
git log fileName # 查看某文件的修改記錄,找背鍋專用
除此之外,還可以通過 –pretty 對提交信息進行定製,比如:
更多規則與定製如下(摘自:Git王者超神之路),或參見:Viewing the Commit History :
format對應的常用佔位符:(注:作者是指最後一次修改文件的人,提交者是提交該文件的人)
佔位符 | 說明 | 佔位符 | 說明 |
---|---|---|---|
%H | 提交對象(commit)的完整哈希字串 | %h | 提交對象的簡短哈希字串 |
%T | 樹對象(tree)的完整哈希字串 | %t | 樹對象的簡短哈希字串 |
%P | 父對象(parent)的完整哈希字串 | %p | 父對象的簡短哈希字串 |
%an | 作者(author)的名字 | %ae | 作者的電子郵件地址 |
%ad | 作者修訂日期(可以用 –date= 選項定製格式) | %ar | 按多久以前的方式顯示 |
%cn | 提交者(committer)的名字 | %ce | 提交者的電子郵件地址 |
%cd | 提交日期 | %cr | 提交日期,按多久以前的方式顯示 |
%s | 提交說明 |
一些其他操作:
選項 | 說明 |
---|---|
-p | 按補丁格式顯示每個更新之間的差異 |
–stat | 顯示每次更新的文件修改統計信息(行數) |
–shortstat | 只顯示 –stat 中最後的行數修改添加移除統計 |
–name-only | 僅在提交信息後顯示已修改的文件清單 |
–name-status | 顯示新增、修改、刪除的文件清單 |
–abbrev-commit | 僅顯示 SHA-1 的前幾個字符,而非所有的 40 個字符 |
–relative-date | 使用較短的相對時間顯示(比如,“2 weeks ago”) |
–graph | 顯示 ASCII 圖形表示的分支合併歷史 |
–pretty | 格式定製,可選選項有:oneline,short,full,Fullerton和format(後跟指定格式) |
還有一些限制log輸出的選項
選項 | 說明 |
---|---|
-(n) | 僅顯示最近的 n 條提交 |
–since, –after | 僅顯示指定時間之後的提交。 |
–until, –before | 僅顯示指定時間之前的提交。 |
–author | 僅顯示指定作者相關的提交。 |
–committer | 僅顯示指定提交者相關的提交。 |
–grep | 僅顯示含指定關鍵字的提交 |
-S | 僅顯示添加或移除了某個關鍵字的提交 |
10.查看某行代碼是誰寫的【git blame】
git blame 文件名 # 查看某文件的每一行代碼的作者,最新commit和提交時間
Tip:
如果你用的IDEA系列的編譯器,右鍵行號,選擇Annotate也可以實現同樣的效果
11.設置Git命令別名【git config –global alias】
可以爲常見的命令起個簡單的別名,就不用每次都敲完整命令,比如可以設置:
status爲st,checkout爲co ; commit爲ci ; branch爲br等
git config --global alias.st status
12.爲重要的commit打標籤【git tag】
對於某些提交,我們可以爲它打上Tag,表示這次提交很重要,
比如爲一些正式發佈大版本的commit,打上TAG,當某個版本
出問題了,通過TAG可以快速找到此次提交,拿到SHA1值,再
去查找問題,比起一個個commit看,省事很多!
Git標籤分兩種:輕量標籤 和 附加標籤
前者只是在提交上加個Tag,指向提交的Hash值;
而後者還會保存打標籤者的信息,時間和附加信息;
git tag 標記內容 # 輕量標籤
git tag -a 標記內容 -m "附加信息" # 附加標籤
如果想爲之前的某次commit打TAG的話,可以先找出SHA1值,設置調下述命令:
git tag -a 標記內容 版本id # 比如:git tag -a v1.1 bcfed96
默認情況,git push不會把標籤推送TAG到遠程倉庫,如果想推送到服務器,可以:
git push origin 標記內容 # 推送某標籤到
# 刪除所有本地倉庫中不存在的TAG:
git push origin --tags
另外,可以在新建分支的時候也加上TAG
git checkout -b 分支名 標記內容
還可以用show命令查看標籤對應的信息
git show 標記內容
如果你想刪除本地Tag:
git tag -d 標記內容
如果是刪除遠程Tag:
git push origin --delete tag 標記內容
13.Git命令自動補全【輸命令的時候按兩次tab鍵】
文件回覆/版本回退
1.文件恢復(未commit)【git checkout】
如果在工作區直接刪除被Git Tracked的文件,暫存區中還會存在該文件,
此時鍵入:git status,會是這樣:
Git告訴你工作區的文件被刪除了,你可以 刪掉暫存區裏的文件或 恢復被刪文件
# 刪除暫存區中的文件:
git rm 文件名
git commit -m "提交說明"
# 誤刪恢復文件
git checkout -- 文件名
# 另外注意:git checkout會拋棄當前工作區的更改!!!不可恢復!!!務必小心!!!
2.文件恢復(已add未commit)【git reset HEAD】
如果更改後add到了暫存區,想恢復原狀,下述指令可以讓文件恢復原狀:
git reset HEAD 文件名
git checkout 文件名
3.版本回退(已commit)【git reset –hard】
文件已經commit了,想恢復成上次commit的版本或者上上次,可以:
git reset HEAD^ # 恢復成上次提交的版本
git reset HEAD^^ # 恢復成上上次提交的版本,就是多個^,以此類推或用~次數
git reset --hard 版本號 # git log查看到的SHA1值,取前七位即可,根據版本號回退
reset命令其實就是:重置HEAD指針,讓其指向另一個commit
而這個動作可能會對工作區與緩存區造成影響,舉個例子
- 本來的分支線:- A - B - C (HEAD, master)
- git reset B後:- A - B (HEAD, master)
解釋:看不到C了,但是他還是存在的,可以通過git reset C版本號找回,前提是
C沒有被Git當做垃圾處理掉(一般是30天)。
reset三個可選參數解析:
- –soft:只是改變HEAD指針指向,緩存區和工作區不變;
- –mixed:修改HEAD指針指向,暫存區內容丟失,工作區不變;
- –hard:修改HEAD指針指向,暫存區內容丟失,工作區恢復以前狀態;
4.查看輸入指令記錄【git reflog】
Git會記住你輸入的每個Git指令,比如上面的git reset 切換成一箇舊的
commit,然後git log後發現新提交的記錄沒了,想切換回新的那次commit,
可以先調git reflog 獲取新commit的SHA1碼,然後git reset 回去。
git reflog
注意:這個指令記錄不會永久保存!Git會定時清理用不到的對象!!!
5.撤銷某次提交【git revert】
有時可能我們想撤銷某次提交所做的更改,可以使用revert命令
git revert HEAD # 撤銷最近的一個提交
git revert 版本號 # 撤銷某次commit
不是真的把提交給撤銷了,而是生成一個新的提交來覆蓋舊的提交,被撤銷的提交
和新的提交記錄都會保存!!!不信你再調一次revert HEAD 會發現被撤銷的更改
又變回來了,另外,每次revert後,都需要發起新的commit!
簡單點說,撤銷的只是文件變化,提交記錄依舊是存在的!
6.查看某次提交修改內容【git show】
git show 提交id # 查看某次commit的修改內容
7.查看某個分支的版本號【git rev-parse】
git rev-parse 分支名 # 查看分支commit的版本號,可以寫HEAD
8.找回丟失對象的最後一點希望【git fsck】
因爲你的某次誤操作導致commit丟失,如果git reflog都找不到,你
可以考慮使用git fsck,找到丟失的對象的版本id,然後恢復即可。
git fsck --lost-found
本地分支
1.分支概念
提交記錄串成的時間線,默認初始創建的分支(時間線) —— master分支,
如果不切換到其他分支上,每次commit生成的快照都會串在這條分支上!
另外還有個 —— HEAD指針,該指針指向正在工作的本地分支,前面的版
本回退其實修改的就是這個HEAD指針的指向!
比如:在master分支上執行四次commit,分支的狀態圖如下
不難發現這樣的規律:
- 每次commit,master都會向前移動一步,指向最新的提交
- HEAD則指向正在工作的本地分支,而git reset修改的就是HEAD指針的指向!
2.創建其他分支的原因
通過兩個場景來體會創建其他分支的必要性
- 場景一:
項目一般都是一步步迭代升級的,有大版本和小版本的更新:
大版本一般是改頭換面的更新,比如UI大改,架構大改,版本是:
v2.0.0這樣;小版本的更新一般是UI小改,Bug修復優化等,版本是:
v2.0.11這樣;只有一條master分支,意味着:你的分支線會
非常非常的長,假如你已經發布到了第二個大版本,然後用戶反饋
第一個版本有很嚴重的BUG,這時候想切回第一個版本改BUG,
然後改完BUG切回第二個大版本,想想也是夠嗆的。
(PS:可能你說我可以對重要的commit打tag,然後找到這個tag
切回去,當然也行這裏是想告訴你引入其他分支會給你帶來的便利)- 場景二:
只有一個master分支的話,假如某次提交衝突了,而這個衝突很難解決或者
解決不了, 那麼,那個整個開發就卡住在這裏了,無法繼續向後進行了!
3.一個最簡單實用的分支管理策略
爲了解決只有一個master分支引起的問題,可以引入分支管理,最簡單的一種策略如下:
在master分支上開闢一個新的develop分支,然後我們根據功能或者業務,再在develop
分支上另外開闢其他分支,完成分支上的任務後,再將這個分支合併到develop分支上!
然後這個功能分支的任務也到此結束,可以刪掉,而當發佈正式版後,再把develop分支
合併到master分支上,並打上TAG。
master與develop分支都作爲長期分支,而其他創建的分支作爲臨時性分支!
簡述各個分支的劃分:
- master分支:可直接用於產品發佈的代碼,就是正式版的代碼
- develop分支:日常開發用的分支,團隊中的人都在這個分支上進行開發
- 臨時性分支:根據特定目的開闢的分支,包括功能(feature)分支,或者預發佈(release)分支,
又或者是修復bug (fixbug)分支,當完成目的後,把該分支合併到develop分支,
然後刪除 該分支,使得倉庫中的常用分支始終只有:master和develop兩個長期分支!
4.分支創建與切換【git branch】
git branch 分支名 # 創建分支
git branch # 查看本地分支
比如在master分支上創建develop分支,此時的分支狀況如下:
git checkout 分支名 # 切換分支
git checkout -b 分支名 # 創建分支同時切換到這個分支
切換到develop分支後,改點東西,再commit,此時的分支狀況如下:
git checkout master 切回master分支,打開之前修改的文件,發現內容
並沒有發生更改,因爲剛剛的更改是在develop上提交的,而master上沒有
變化,此時的分支狀況如下:
5.分支的合併【git merge】 VS 【git rebase】
Git中,可以使用 git merge 和 git rebase 兩個命令來進行分支的合併
git merge合併分支
合併的方式分爲兩種:快速合併 和 普通合併,兩者的區別在於:
前者合併後看不出曾經做過合併,而後合併後的歷史會有分支記錄,如圖:
快速合併: 普通合併 :
示例:
快速合併,把develop分支合併到master分支上,來到master分支後,鍵入下述命令
git merge develop
打開文件:
普通合併,切到develop分支下,修改note_2.txt的內容,再通過下述指令合併分支:
注:–no-ff參數表示禁用快速合併!
git merge --no-ff -m "合併的信息(TAG)" develop
分支線情況:
git reabse合併分支
rebase(衍合或變基),發現很多所謂的教程把這個東西寫得太深奧了,
其實並沒有那麼複雜,只是這種合併會使得樹整潔,易於跟蹤,
舉個簡單的例子來對比下,有一個項目由兩個人同時開發,
當前遠程倉庫的提交記錄是這樣的:
然後A和B各自開了一個條分支來完成相應功能,接着他們在自己的
分支上都做了多次的commit,此時兩人的分別分支線是這樣的:
A先合併,再到B合併,這裏我們假設兩人做的是完全不關聯的模塊,合並沒有衝突
merge合併
rebase合併
用法:
git rebase 想合併到哪個分支的分支名
6.解決合併衝突
在我們合併分支的時候,有時會遇到合併衝突,然後合併失敗的問題,
此時需要我們先解決衝突後才能進行合併,個人開發倒很少會遇到,多人
開發的時候遇到合併衝突則是家常便飯。
一個最簡單的例子,A和B在develop分支上開闢出兩個分支來完成相關的
功能,A做完了,把自己的分支合併到develop分支,此時develop分支向前
移動了幾次commit,接着B也完成了他的功能,想把自己分支合併到develop
分支,如果改動的文件和和A改動的文件相同的話,此時就會合並失敗,
然後需要處理完衝突,才能夠繼續合併!簡單模擬下這個例子,先試試merge!
merge分支後處理衝突
打開衝突文件,然後處理衝突部分,保留什麼代碼你自己決定,處理完後把
<<< 和 >>> 這些去掉:
處理後:
然後add,然後commit即可,合併結束:
此時的分支線:
接着試試
rebase分支後處理衝突
重新來一遍,然後把A直接merge到master,再切到B,rebase master,此時出現
合併衝突,這裏有三個可選的操作:
git rebase --continue # 處理完衝突後,繼續處理下一個補丁
git rebase --abort # 放棄所有的衝突處理,恢復rebase前的情況
git rebase --skip # 跳過當前的補丁,處理下一個補丁,不建議使用,補丁部分的commit會丟失!
好的,有三次補丁要處理,一個個來:
處理後:
接着git add 添加修改後的文件,git rebase –continue繼續處理補丁:
接着重複之前的過程:
處理後:
第三個補丁是與A分支無關聯的改動,所以沒有衝突,所以也就直接合並了!
如果合併中途出了什麼差錯可以git rebase –abort 恢復rebase前的狀況!
最後看下分支線會發現是一條直線,這也是用rebase合併分支的優點:
附上栗子,可以自己試試:GitTest.7z
7.刪除分支
對於合併完的分支,基本都沒什麼作用了,可以使用下述命令刪除:
git branch -d 分支名 # 刪除分支,分支上有未提交更改是不能刪除的
git branch -D 分支名 # 強行刪除分支,儘管這個分支上有未提交的更改
8.恢復誤刪分支
兩步,找出被刪除分支的最新commit的版本號,然後恢復分支
git log --branches="被刪除的分支名" # 找到被刪分支最新的commitb版本號
git branch 分支名 版本號(前七位即可) # 恢復被刪分支
9.切換分支時保存未commit的更改【git stash】
有時我們可能在某個分支上正編寫着代碼,然後有一些突發的情況,需要
我們暫時切換到其他分支上,比如要緊急修復bug,或者切換分支給同事
review代碼,此時如果直接切換分支是會提示切換失敗的,因爲這個分支
上做的更改還沒有提交,你可以直接add後commit,然後再切換,不過我們
習慣寫完某個功能再提交,我們想:
先暫存這個分支上的改動,切去其他分支上搞完事,然後回來繼續
繼續在之前的改動上寫代碼。
那麼可以使用:
git stash # 保存當前的改動
然後放心的切換分支,然後再切換回來,接着使用:
git stash apply # 恢復保存改動
另外有一點一定要注意!!!可以stash多個改動!!如果你切換
到另一個分支又stash了,然後切換回來stash apply是恢復成另一個
分支的stash!!!
如果你這樣stash了多次的話,我建議你先鍵入:
git stash list # 查看stash列表
找到自己想恢復的那個
比如我這裏恢復的應該是netword上的stash,而第一個stash是devlop上的
直接git stash apply恢復的就是這個,然而恢復的應該是network的那個stash:
git stash apply stash@{1}
就是這樣,按自己需要恢復即可!
10.分支重命名
git branch -m 老分支名 新分支名 # 分支重命名
遠程倉庫與遠程分支
1.遠程倉庫簡述
用於代碼託管,可以自己搭建遠程倉庫,或者選擇專業的代碼託管平臺:
自己搭建的好處有:可控,內網安全,可以做一些定製,比如集成編譯,IM等,
當然,肯定是需要一些學習成本的,(PS:我廠就是自己搭的Gitlab,自己配置
還是比較麻煩的,簡單點的可以試試 Gogs)
常見的代碼託管平臺(自己搜關鍵字去~):
Github,Git@OSC,GitCafe,GitLab,coding.net,gitc,BitBucket,Geakit,Douban CODE
2.推送本地倉庫到遠程倉庫【git push】
首先建立好與本地倉庫同名的遠程倉庫,然後複製下遠程倉庫的地址,比如:
鍵入下述命令關聯本地與遠程倉庫
git remote add origin 遠程倉庫地址
可以鍵入下述命令可查看遠程倉庫狀況
接着把本地倉庫推送到遠程倉庫,這裏的 -u參數 作爲第一次提交使用,
作用是把本地master分支和遠程master分支關聯起來(設置默認遠程主機),
後續提交不需要這個參數!
git push -u origin master
另外,如果想修改遠程倉庫地址,可鍵入:
git remote set-url origin 遠程倉庫地址
# 也可以先刪除origin後再添加
git remote rm origin # 刪除倉庫關聯
git remote add origin 遠程倉庫地址 # 添加倉庫關聯
或直接修改.git文件夾中的config文件,直接替換圈住位置
還要說明一點,origin 並不是固定的東西,只是後面倉庫地址的一個 別名!!
可以寫成其他的東西,然後你也可以設置多個倉庫關聯,用不同的別名標誌,比如:
git remote add github https://github.com/coder-pig/SimpleTea.git
git remote add osc git@git.oschina.net:coder-pig/SimpleTea.git
3.克隆遠程倉庫【git clone】
把項目推送到遠程倉庫後,其他開發者就可以把項目clone到本地
git clone 倉庫地址 # 克隆項目到當前文件夾下
git clone 倉庫地址 目錄名 # 克隆項目到特定目錄下
4.同步遠程倉庫更新【git fetch】VS 【git pull】
關於獲取遠程服務器更新的方式有兩種,他們分別是fetch和pull,
儘管都可以獲取遠程服務器更新,但是兩者卻又是不一樣的。
git fetch:
僅僅只是從遠處服務器獲取到最新版本到本地,假如你不去合併(merge)
的話,本地工作空間是不會發生變化的!比如:
我們在Github上創建一個README.md文件,然後調 git fetch 去獲取遠程
倉庫的更新。
git pull:
一步到位,或者說:pull = fetch + merge,比如:同樣修改Github上的
README.md 文件,然後git pull 同步遠程倉庫的更新
區別顯而易見,實際開發中,使用git fetch會更安全一些,畢竟merge的時候
我們可以查看更新的情況,再決定是否進行合併,當然看實際需要吧!
5.推送本地分支到遠程倉庫
按照前面所講,在本地開闢分支來完成某些工作,本地提交了多次後,
你想把分支推送到遠程倉庫,此時遠程倉庫並沒有這個分支,你可以:
git push origin 分支名 # 推送本地分支的內容到遠程分支
6.查看遠程分支
git branch -r # 查看所有分支
7.拉取遠程分支到本地倉庫
git checkout -b 本地分支 遠程分支 # 會在本地新建分支,並自動切換到該分支
git fetch origin 遠程分支:本地分支 # 會在本地新建分支,但不會自動切換,還需checkout
git branch --set-upstream 本地分支 遠程分支 # 建立本地分支與遠程分支的鏈接
8.刪除遠程分支
git push origin :分支名
9.重命名遠程分支
先刪除遠程分支,然後重命名本地分支,接着再Push到遠程倉庫
10.爲項目添加SSH Key免去提交輸入賬號密碼的麻煩
不知道細心的你有沒有發現,倉庫地址除了Https外,還有一個SSH,
這裏我們簡單介紹下兩者的區別,第一點:使用Https url可以任意克隆
Github上的項目;而是用SSH url克隆的話,你必須是項目的擁有者或
管理員,而且還要添加SSH Key,否則會無法克隆。還有一點是,
Https每次push都需要輸入用戶名和密碼,而使用SSH則不需要輸入
用戶名如果配置SSH Key時設置了密碼,則需要輸入密碼,否則直接
git push就可以了!
另外,SSH,Secure shell(安全外殼協議),專爲遠程登陸會話
與其他網絡服務提供安全性的協議,而SSH傳輸的數據是可以經過壓縮的,
可以加快傳輸的速度,出於安全性與速度,我們優先考慮使用SSH協議,
而SSH的安全驗證規則又分爲基於密碼和基於密鑰兩種!
我們這裏用的是基於第二種的,即在本地創建一對密鑰,
公鑰(id_rsa.pub)和私鑰(id_rsa),然後把公鑰的內容貼到
Github賬號的ssh keys中,這樣就建立了本地和遠程的認證關係,
當我們再push到遠程倉庫,會將你本地的公共密鑰與服務器的進行匹配,
如果一致驗證通過直接推送更新!
下面我們來建立ssh key,首先來到電腦的根目錄下,這裏假定我們沒
創建過SSH key:
執行完ssh-keygen那個指令後,後面依次要你輸入文件名,
直接回車會生成兩個默認的祕鑰文件,接着提示輸入密碼,
直接回車,如果這裏你輸入密碼了的話,那麼push的時候
你還是需要輸入密碼,接着又輸多一次密碼,同樣回車,
然後出現最下面的這串東西就說明ssh key已經創建成功了!
我們接着可以用編輯器打開id_rsa.pub文件或者鍵入:
clip <id_rsa.pub
複製文件內容,然後打開Github,點擊你的頭像,選擇:Settings,
然後點擊左側SSH Keys,然後New SSH Key
然後Github會給你發來一個提示創建了一個新ssh key的郵件,
無視就好,接下來我們可以鍵入:ssh -T [email protected],
然後如果你上面設置過密碼則需要輸入密碼,
否則直接輸入yes然後一直按回車就好!,最後出現Hi xxx那句話
就說明ssh key配置成功了!
PS:其他遠程倉庫配置方法與此類同,
內容參考自:https://help.github.com/articles/generating-an-ssh-key/
附1:Github客戶端
其實,安裝好Git後,就一有一個GitGui的東東了,就可以直接
用有用戶界面的Git來做版本管理的工作了,而Github客戶端則是
Github給我們提供的一個專門用來管理Github項目的一個工具而已。
比如,假如你裝了Github客戶端,在Clone項目的時候,你只需點擊:
就能直接把項目clone下來,就是一些Git操作的圖形化罷了,首先來到下面的鏈接
下載Github客戶端:https://desktop.github.com/
文件很小,後面點擊運行文件後,他還要在線下載安裝,100多m,
然後傻瓜式安裝,安裝完成後,會自動打開Github客戶端,然後
使用你的Github賬號登陸,接着他會默認爲你創建SSH Key信息,
接着的你自己摸索了!
這裏另外補充一點,就是win 8.1裝Github客戶端的問題,
昨晚安裝的時候一直報這個錯誤:
直接,win + x,選擇”命令行提示符(管理員)“,執行以下下面的這個指令:
%SYSTEMROOT%\SYSTEM32\REGSVR32.EXE %SYSTEMROOT%\SYSTEM32\WUAUENG.DLL
然後再點擊Github的安裝程序,等待安裝完成即可,下載並不需梯子。
附2:刪除Git倉庫
點擊進入你的倉庫,點擊Setting,拉到最後:
點擊Delete this repository
彈出的對話框中輸入要刪除的倉庫名稱,接着點擊刪除
附3:爲開源項目貢獻代碼
你可以Clone別人的開源項目,在看別人代碼的時候,你覺得作者有
某些地方寫得不好,寫錯,或者你有更好的想法,你在本地修改後,
想把修改push推送到開源項目上,想法很好,但是你不是項目的擁
有着和參與者,是無法推送更改的!!!這樣是爲了
避免熊孩子,畢竟熊孩子無處不在,參與開源項目的方法有兩種:
第一種方法:
是讓作者把你加爲寫作者,添加協作者流程:點擊倉庫的Settings
–>Collaborators然後輸入想添加的人的用戶名或者郵箱,點擊
添加即可。
第二種方法:
點擊Fork按鈕,把這個項目fork到自己的賬號下,然後Clone
到本地,然後做你想做的修改,commit提交,然後push到自己賬
號裏的倉庫,然後打開開源項目,點擊,然後新建一個
pull request,接着設置自己的倉庫爲源倉庫,設置源分支,
目標倉庫與目標分支,然後還有pull request的標題和描述信息,
填寫完畢後,確定,這個時候開源項目的作者就會收到一個pull
request的請求,由他來進行審覈,作者審查完代碼覺得沒問題
的話,他可以點擊一下merge按鈕即可將這個pull request合併
到自己的項目中,假如作者發現了你代碼中還有些bug,他可以
通過Pull Request跟你說明,要修復了xxBUG才允許合併,那麼
你再修改下BUG,提交,更改後的提交會進入Pull Request,
然後作者再審覈這樣!
PS:假如作者不關閉或者merge你的這個Pull Request,你可以一直
commit騷擾主項目…( ╯□╰ )
Git工作流
關於Git工作流,看到一篇圖文並茂很好的文章,就不重複造輪子了,
此處只是做下對應工作流的簡述,詳情見:Git Workflows and Tutorials
1.集中式工作流
類似於SVN,不過只有一條master分支,然後一羣人就在這條分支上嗨,比如有小A和小B:
(衝突解決參照上面的套路)
- 1.項目管理者初始化倉庫,然後推到遠程倉庫
- 2.其他人克隆遠程倉庫項目到本地
- 3.小A和小B完成各自的工作
- 4.小A先完成了,git push origin master 把代碼推送到遠程倉庫
- 5.小B後完成了,此時推送代碼到遠程倉庫,出現文件修改衝突
- 6.小B需要先解決衝突,git pull –rebase origin master,然後rebase慢慢玩
- 7.小B把衝突解決後,git push origin master 把代碼推送到遠程倉庫
2.功能分支工作流
和集中式分部流相比只是分支再不是隻有master,而是根據功能開闢新的分支而已,示例:
注:這裏的倉庫管理者是擁有倉庫管理權限的人
- 1.小A要開發新功能,git branch -b new-feature 開闢新分支
- 2.小A在new-feature上新功能相關的編寫,他可以這個分支推到遠程倉庫
- 3.功能完成後,發起請求pull request(合併請求),把new-feature合併到master分支
- 4.倉庫管理員可以看到小A的更改,可以進行一些評註,讓小A做某些更改,
然後再發起pull request,或者把pull request拉到本地自行修改。- 5.倉庫管理員覺得可以了,合併分支到master上,然後把new-feature分支刪掉
3.Gitflow工作流
其實就是功能分支工作流做了一些規範而已,大概流程參見上面Git分支裏的:
一個最簡單實用的分支管理策略。
4.Forking工作流
分佈式工作流,每個開發者都擁有自己獨立的倉庫,和上面的附3:爲開源項目貢獻代碼
套路類似,把項目fork到自己的遠程倉庫,完成相應更改,然後pull request到源倉庫,
源倉庫管理者可以決定是否合併。
5.Pull Request工作流
和Forking工作流類似,Pull Requests是Bitbucket上方便開發者之間協作的功能
查缺補漏
一些高級技巧,工具,插件安利
1.巨好用的Git圖形化工具SourceTree
命令行雖酷炫可裝逼,但是有時用圖形化工具還是能提高我們不少效率的,
如題,SourceTree,官網下載地址:https://www.sourcetreeapp.com/
2.把提交的commit從一個分支放到另一個分支【git cherry-pick】
有時你可能需要把某個分支上的commit放到另一個分支上,這個時候可以
使用cherry-pick,比如有下面這樣兩個分支:
master分支:A -> B -> C
feature分支:a -> b
現在想把feature上的b,放到master的C後,可以這樣:
- Step 1:切換到feature分支上,git log拿到b commit的版本號(SHA1)
- Step 2:切換到master分支,鍵入:git cherry-pick 版本號
出現上面這種情況的話說明出現衝突了,處理衝突後,git add 和 git commit 走一波
即可。
問題解決
1.fatal: refusing to merge unrelated histories
問題描述:在Github上新建了一個倉庫,裏面帶有一個licence文件,然後本地
本地項目想推到這個遠程倉庫上,git remote 設置了遠程倉庫後,push提示先pull,
pull的時候就報這個錯了,解決方法如下:
git pull origin master --allow-unrelated-histories
待續…(最近更新:2017.10.26)
編輯日誌:
- 2017.5.3: 添加.gitignore注意事項
- 2017.9.5: 排版與內容優化,勘誤,新增查缺補漏
- 2017.10.26:新增問題解決模塊