集中式:
版本庫是集中存放在中央服務器的,而幹活的時候,用的都是本身的電腦,因此要先從中央服務器取得最新的版本,而後開始幹活,幹完活了,再把本身的活推送給中央服務器。集中式的缺點就是:工做必須在同一網絡下,傳輸速率慢,並且一旦中央服務器宕機,全部人不能工做。
分佈式:
布式版本控制特色是:每一個人的電腦上都是一個完整的版本庫,這樣,你工做的時候,就不須要聯網了,由於版本庫就在你本身的電腦上。若是某一我的的電腦壞掉了沒關係,隨便從其餘人那裏複製一個就能夠了。分佈式版本控制系統一般也有一臺充當「中央服務器」的電腦,但這個服務器的做用僅僅是用來方便「交換」你們的修改,沒有它你們也同樣幹活,只是交換修改不方便而已。git
版本庫又名倉庫,英文名repository,你能夠簡單理解成一個目錄,這個目錄裏面的全部文件均可以被Git管理起來,每一個文件的修改、刪除,Git都能跟蹤,以便任什麼時候刻均可以追蹤歷史,或者在未來某個時刻能夠「還原」。
建立版本庫github
#找一個空目錄,做爲工做空間 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test (master) $ pwd /e/code_test/git_test #建立一個目錄 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test (master) $ mkdir learngit #進入目錄 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test (master) $ cd learngit/ #將此目錄初始化爲倉庫 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git init Initialized empty Git repository in E:/code_test/git_test/learngit/.git/
此時就會看見該目錄下:shell
說明倉庫初始化成功!!!
實戰操做:
需求:編寫一個文件,將其放入git倉庫管理。vim
#編寫一個文件: Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ vim readme.txt 加入: Git is a version control system. Git is free software. #告訴git,把文件添加到倉庫 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git add readme.txt #告訴git,把文件提交到倉庫 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git commit -m "wrote a readme file" #查看此時工做空間的狀態 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git status On branch master nothing to commit, working tree clean #出現這句話表示工做空間很乾淨,最好的狀態。 補充:這裏先add而後在commit的意義是,由於commit能夠一次提交不少文件,因此你能夠屢次add不一樣的文件。
#第一步,修改倉庫中的一個文件 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ vim readme.txt 添加一行: Git is good software. #第二步,查看此時的狀態 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git status 注意打印的內容: On branch master #在master主分支上 Changes not staged for commit: #文件被修改,可是沒有提交 (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: readme.txt #具體被modify的文件 no changes added to commit (use "git add" and/or "git commit -a") #查看哪裏被修改了 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git diff readme.txt diff --git a/readme.txt b/readme.txt index 46d49bf..f2cbe56 100644 --- a/readme.txt +++ b/readme.txt @@ -1,2 +1,3 @@ #表示新添加了一行 Git is a version control system. Git is free software. +Git is good software. #這一行是新添加的。 #此時咱們在提交 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git add readme.txt #查看此時的工做空間的狀態 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git status On branch master Changes to be committed: #提示 ,此時須要提交 (use "git reset HEAD <file>..." to unstage) modified: readme.txt #最終咱們把修改的提交 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git commit -m "change one line on readme.txt" #查看此時的工做空間的狀態 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git status On branch master nothing to commit, working tree clean #表示提交成功,此時的工做空間很乾淨!!
在倉庫中的內容通過屢次修改以後,咱們也不知道每個版本具體修改了什麼內容,此時可使用git log顯示從最近到最遠的提交日誌,咱們能夠看到2次提交,最近的一次是change one line on readme.txt,最先的一次是wrote a readme file。
也可使用:git log - -pretty=oneline 輸出少許的信息。
標紅框的表示的是,此時修改的版本號。
通過上面的鋪墊,咱們學習一下,若是進行版本的回退:
首先,Git必須知道當前版本是哪一個版本,在Git中,用HEAD表示當前版本,也就是最新的提交1094adb...(注意個人提交ID和你的確定不同),上一個版本就是HEAD^,上上一個版本就是HEAD^^,固然往上100個版本寫100個^比較容易數不過來,因此寫成HEAD~100。服務器
#退回到上一個版本 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git reset --hard HEAD^ HEAD is now at b2d3770 wrote a readme file #使用git log查看一下日誌 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git log
最近一次的change one line on readme.txt已經不存在了!網絡
#如今又想回到當初的版本,怎麼辦? Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git reset --hard 93fc40 #最後一個參數,是須要回到的版本的版本號(不用全寫) HEAD is now at 93fc40d change one line on readme.txt #此時再次查看git log Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git log
OK,又回來了!app
#可是若是不知道版本號,怎麼辦? Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git reflog 93fc40d (HEAD -> master) HEAD@{0}: reset: moving to 93fc40 b2d3770 HEAD@{1}: reset: moving to HEAD^ 93fc40d (HEAD -> master) HEAD@{2}: commit: change one line on readme.txt b2d3770 HEAD@{3}: commit (initial): wrote a readme file 你會發現的你的操做動做,都被記錄下來了,此時再去其中尋找版本號便可。
這種版本的來回切換,到底原理是什麼呢?
Git的版本回退速度很是快,由於Git在內部有個指向當前版本的HEAD指針,當你回退版本的時候,Git僅僅是把HEAD指向change one line on readme.txt。
HEAD指向改成那個版本,當前版本就是哪個。ssh
工做區:電腦裏能看到的目錄。
版本庫:工做區有一個隱藏目錄.git,這個目錄就是是Git的版本庫。
Git的版本庫裏存了不少東西,其中最重要的就是稱爲stage(或者叫index)的暫存區,還有Git爲咱們自動建立的第一個分支master,以及指向master的一個指針叫HEAD。
以前講了咱們把文件往Git版本庫裏添加的時候,是分兩步執行的:分佈式
#修改工做區的中一個文件 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ vim readme.txt #而後添加的暫存區 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git add readme.txt #再次修改文件 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ vim readme.txt #提交 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git commit -m "two times changes" #查看此時的倉庫狀態 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git status On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: readme.txt no changes added to commit (use "git add" and/or "git commit -a") 發現了第二次修改的沒有提交! 這是什麼緣由的呢? 第一次修改 -> git add -> 第二次修改 -> git commit,Git管理的是修改,當你用git add命令後,在工做區的第一次修改被放入暫存區,準備提交,可是,在工做區的第二次修改並無放入暫存區,因此,git commit只負責把暫存區的修改提交了,也就是第一次的修改被提交了,第二次的修改不會被提交。 此時查看工做區和版本庫裏面最新版本的區別: $ git diff HEAD -- readme.txt
果真不一樣的地,就在第二次的修改。
若是咱們:第一次修改 -> git add -> 第二次修改 -> git add -> git commit
而後,版本庫中最新的版本就和當前工做空間中的一致了。ide
狀況一:對文件作了修改,可是沒有add到暫存區。
#第一步:對文件作了不正確的修改 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ vim readme.txt #第二步查看倉庫版本庫狀態 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git status On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: readme.txt no changes added to commit (use "git add" and/or "git commit -a") # git checkout -- readme.txt所有撤銷在工做區的修改 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git checkout -- readme.txt 再次查看文件,以前的修改被撤銷。 #查看此時的版本庫的狀態 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git status On branch master nothing to commit, working tree clean
狀況二:對文件作了錯誤的修改,而且已經add到暫存區中
#第一步:對文件作了不正確的修改 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ vim readme.txt #二:添加到暫存區 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git add readme.txt #查看狀態 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: readme.txt #用命令git reset HEAD <file>能夠把暫存區的修改撤銷掉(unstage) Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git reset HEAD readme.txt #再次查看版本庫狀態 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git status On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: readme.txt no changes added to commit (use "git add" and/or "git commit -a") #最後再次撤銷工做區的修改便可 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git checkout -- readme.txt #查看此時的版本庫狀態 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git status On branch master nothing to commit, working tree clean
在Git中,刪除也是一個修改操做。
#在工做空間中刪除一個文件: Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ rm -rf test.txt #查看版本庫的狀態 $ git status On branch master Changes not staged for commit: (use "git add/rm <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) deleted: test.txt no changes added to commit (use "git add" and/or "git commit -a") 此時git知道你在刪除一個文件,此時版本庫和工做空間中的文件不一致了。 #從版本庫中將文件刪除,保證版本庫和工做空間中一致 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git rm test.txt #再次查看版本庫中的狀態 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) deleted: test.txt #最終提交一下這次的刪除操做 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git commit -m "remove test.txt" #再次查看版本庫中的狀態 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git status On branch master nothing to commit, working tree clean
在版本回退裏,你已經知道,每次提交,Git都把它們串成一條時間線,這條時間線就是一個分支。截止到目前,只有一條時間線,在Git裏,這個分支叫主分支,即master分支。HEAD嚴格來講不是指向提交,而是指向master,master纔是指向提交的,因此,HEAD指向的就是當前分支。
一開始的時候,master分支是一條線,Git用master指向最新的提交,再用HEAD指向master,就能肯定當前分支,以及當前分支的提交點:
每次提交,master分支都會向前移動一步,這樣,隨着你不斷提交,master分支的線也愈來愈長:
當咱們建立新的分支,例如dev時,Git新建了一個指針叫dev,指向master相同的提交,再把HEAD指向dev,就表示當前分支在dev上:
Git建立一個分支很快,由於除了增長一個dev指針,改改HEAD的指向,工做區的文件都沒有任何變化!
不過,從如今開始,對工做區的修改和提交就是針對dev分支了,好比新提交一次後,dev指針往前移動一步,而master指針不變:
假如咱們在dev上的工做完成了,就能夠把dev合併到master上。Git怎麼合併呢?最簡單的方法,就是直接把master指向dev的當前提交,就完成了合併:
合併完分支後,甚至能夠刪除dev分支。刪除dev分支就是把dev指針給刪掉,刪掉後,咱們就剩下了一條master分支:
#建立dev分支,而後切換到dev分支: Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git checkout -b dev Switched to a new branch 'dev' #查看當前分支 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev) $ git branch * dev Master #在Dev分支上,修改文件 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev) $ vim readme.txt #添加到暫存區並提交 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev) $ git add readme.txt Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev) $ git commit -m "dev branch test" [dev 1d10b07] dev branch test 1 file changed, 1 insertion(+) #此時切換到master分支 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev) $ git checkout master Switched to branch 'master' 此時查看剛剛修改的內容,發現不見了,在mater分支上並無修改過。 #把dev分支的工做成果合併到master分支上: Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git merge dev Updating 8c466d3..1d10b07 Fast-forward readme.txt | 1 + 1 file changed, 1 insertion(+) 注意:上面的Fast-forward信息,Git告訴咱們,此次合併是「快進模式」,也就是直接把master指向dev的當前提交,因此合併速度很是快。 #合併後,將Dev這個分支刪除 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git branch -d dev Deleted branch dev (was 1d10b07). #查看此時的分支 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git branch * master #只有一個master,Dev被刪除
衝突的由來:
在master分支上新建一個update分支:
而後在update上進行了add和commit:
而後切換到master分支,而且進行了add和commit:
此時兩個分支上的都作了修改和提交,而且修改的內容不同,Git沒法執行「快速合併」,只能試圖把各自的修改合併起來,但這種合併就可能會有衝突。
命令實戰:
#建立並切換到一個分支上 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git checkout -b update Switched to a new branch 'update' #修改文件、add和commit Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (update) $ vim readme.txt Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (update) $ git add readme.txt Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (update) $ git commit -m "change woman" [update 01c7377] change woman 1 file changed, 1 insertion(+), 1 deletion(-) #切換到master分支 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (update) $ git checkout master Switched to branch 'master' #修改、add和commit Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ vim readme.txt Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git add readme.txt Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git commit -m "change mans" [master 0ed89f1] change mans' 1 file changed, 1 insertion(+), 1 deletion(-) #分支合併 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git merge update Auto-merging readme.txt CONFLICT (content): Merge conflict in readme.txt Automatic merge failed; fix conflicts and then commit the result. #查看此時的倉庫狀態 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master|MERGING) $ git status On branch master You have unmerged paths. #合併出現問題 (fix conflicts and run "git commit") (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add <file>..." to mark resolution) both modified: readme.txt no changes added to commit (use "git add" and/or "git commit -a") #查看文件,手動解決衝突
#再次提交 $ git add readme.txt Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master|MERGING) $ git commit -m "conflict fixed" [master 2455cde] conflict fixed #查看狀態(衝突解決) Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git status On branch master nothing to commit, working tree clean #用帶參數的git log也能夠看到分支的合併狀況: $ git log --graph --pretty=oneline --abbrev-commit * 2455cde (HEAD -> master) conflict fixed |\ | * 01c7377 (update) change woman * | 0ed89f1 change mans' |/ * 1d10b07 dev branch test * 8c466d3 remove test.txt * b4924af add file test.txt * c204725 second time change * bb14dd9 two times changes * 93fc40d change one line on readme.txt * b2d3770 wrote a readme file 上面的log可能不容易懂,如今給他換成圖形
一般,合併分支時,若是可能,Git會用Fast forward模式,但這種模式下,刪除分支後,會丟掉分支信息。若是要強制禁用Fast forward模式,Git就會在merge時生成一個新的commit,這樣,從分支歷史上就能夠看出分支信息。使用--no-ff方式的git merge就會強制禁止Fast forward模式。
#建立並切換到分支 dministrator@WIN10-901241016 MINGW64 /e/code_test/git_te st/learngit (master) $ git checkout -b dev Switched to a new branch 'dev' #修改文件,並add和commit Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev) $ vi readme.txt Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev) $ git add readme.txt Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev) $ git commit -m "add one line in readme.txt" [dev 47cf755] add one line in readme.txt 1 file changed, 1 insertion(+) #切換到master Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev) $ git checkout master Switched to branch 'master' Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git branch dev * master #準備合併dev分支,請注意--no-ff參數,表示禁用Fast forward: Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git merge --no-ff -m "merge with no-ff" dev Merge made by the 'recursive' strategy. readme.txt | 1 + 1 file changed, 1 insertion(+) 注意:本次合併建立了一個新的commit,因此加上-m參數,把commit描述寫進去。 #查看歷史分支 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git log --graph --pretty=oneline --abbrev-commit
最終不使用Fast forward模式,merge後就像這樣:
軟件開發中,bug就像屢見不鮮同樣。有了bug就須要修復,在Git中,因爲分支是如此的強大,因此,每一個bug均可以經過一個新的臨時分支來修復,修復後,合併分支,而後將臨時分支刪除。
需求:接到一個修復一個代號101的bug的任務時,很天然地,你想建立一個分支issue-101來修復它,可是,等等,當前正在dev上進行的工做尚未提交,並非你不想提交,而是工做只進行到一半,還無法提交,預計完成還需1天時間。可是,必須在兩個小時內修復該bug,怎麼辦?
#建立並切換到一個分支 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git checkout -b dev Switched to a new branch 'dev' #在dev分支上進行工做 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev) $ vim readme.txt #此時須要切換到master上,並修改內容,可是此時查看狀態 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev) $ git status On branch dev Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: readme.txt no changes added to commit (use "git add" and/or "git commit -a") 很顯然這次的修改並無提交,可是還有工做沒有完成,不能提交,此時咱們: Git還提供了一個stash功能,能夠把當前工做現場「儲藏」起來,等之後恢復現場後繼續工做: Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev) $ git stash Saved working directory and index state WIP on dev: 2752807 merge with no-ff #查看版本庫狀態 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev) $ git status On branch dev nothing to commit, working tree clean 工做空間被保存,此時能夠切換至master,修改bug。 #切換至master,並建立臨時的分支 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev) $ git checkout master Switched to branch 'master' Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git checkout -b issue-101 Switched to a new branch 'issue-101' #修改bug,並add和commit Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (issue-101) $ vim readme.txt Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (issue-101) $ git add readme.txt Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (issue-101) $ git commit -m "bug already update" [issue-101 5964260] bug already update 1 file changed, 1 insertion(+), 1 deletion(-) #切換到master分支,並完成合並,最後刪除issue-101分支 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (issue-101) $ git checkout master Switched to branch 'master' Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git merge --no-ff -m "merged bug fix 101" issue-101 Merge made by the 'recursive' strategy. readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git branch -d issue-101 Deleted branch issue-101 (was 5964260). #修復bug以後,回到工做區繼續幹活 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master) $ git checkout dev Switched to branch 'dev' #查看此時的工做區狀態 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev) $ git status On branch dev nothing to commit, working tree clean #很乾淨 #用git stash list命令看看,剛纔的工做現場存到哪去了? Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev) $ git stash list stash@{0}: WIP on dev: 2752807 merge with no-ff #回覆工做現場,通常有兩個方法: 一是用git stash apply恢復,可是恢復後,stash內容並不刪除,你須要用git stash drop來刪除; 另外一種方式是用git stash pop,恢復的同時把stash內容也刪了: Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev) $ git stash pop #查看此時的工做空間的狀態 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev) $ git status On branch dev Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: readme.txt no changes added to commit (use "git add" and/or "git commit -a") 此時回到了剛剛工做是的狀態!!!
補充:
若是想屢次使用stash,先用git stash list查看,而後恢復指定的stash,用命令:
#git stash apply stash@{0}
軟件開發中,總有無窮無盡的新的功能要不斷添加進來。添加一個新功能時,你確定不但願由於一些實驗性質的代碼,把主分支搞亂了,因此,每添加一個新功能,最好新建一個feature分支,在上面開發,完成後,合併,最後,刪除該feature分支。
需求:開始須要新開發一個功能,此時創建一個新的分支進行開發,開發完成以後add和commit,而後進入dev分支,進行分支的合併,可是此時的這個任務取消,須要刪除這個分支,可是Git提示,新建的分支沒有被合併不能刪除,若是刪除,將丟失掉修改,若是要強行刪除,須要使用大寫的-D參數。
#建立分支,並修改內容,add和commit Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev) $ git checkout -b new-option Switched to a new branch 'new-option' M readme.txt Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (new-option) $ vim feature Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (new-option) $ git add feature warning: LF will be replaced by CRLF in feature. The file will have its original line endings in your working directory. Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (new-option) $ git commit -m " add feature" [new-option f0e5187] add feature 1 file changed, 1 insertion(+) create mode 100644 feature #切換到dev Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (new-option) $ git checkout dev Switched to branch 'dev' M readme.txt #強行刪除剛剛編輯的分支 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev) $ git branch -D new-option Deleted branch new-option (was f0e5187). #查看此時的工做空間的狀態 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev) $ git status On branch dev nothing to commit, working tree clean
發佈一個版本時,咱們一般先在版本庫中打一個標籤(tag),這樣,就惟一肯定了打標籤時刻的版本。未來不管何時,取某個標籤的版本,就是把那個打標籤的時刻的歷史版本取出來。因此,標籤也是版本庫的一個快照。
Git的標籤雖然是版本庫的快照,但其實它就是指向某個commit的指針,因此,建立和刪除標籤都是瞬間完成的。
雖然每次的commit都有一個commit號,可是這個號是隨機生成的,不是很好找。使用標籤的話就很容易找出相應的版本,而後會很快的找出對應的版本。
#切換到須要打標籤的分支上: Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev) $ git branch * dev master #敲命令git tag <name>就能夠打一個新標籤: Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev) $ git tag v1.0 #查看標籤 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev) $ git tag v1.0 注意:默認標籤是打在最新提交的commit上的。
#有時候,若是忘了打標籤,好比昨天的標籤忘記打嗎該怎麼辦? #找到歷史提交的commit id: Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev) $ git log --pretty=oneline --abbrev-commit 15d01da (HEAD -> dev) add shell script 300b129 add test.txt 993ddf5 (tag: v1.0, master) Initial commit #對300b129 add test.txt打標籤 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev) $ git tag v0.9 300b129 #查看標籤 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev) $ git tag v0.9 v1.0 注意:標籤不是按時間順序列出,而是按字母排序的。 #用git show <tagname>查看標籤信息: Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev) $ git show v0.9 commit 300b1296640faab2ad0efddae2bd24fa11993d4c (tag: v0.9) Author: zy <m18726234267@163.com> Date: Wed Mar 6 10:00:44 2019 +0800 add test.txt diff --git a/test.txt b/test.txt new file mode 100644 index 0000000..8d3e51d --- /dev/null +++ b/test.txt @@ -0,0 +1 @@ +this is a test text. #固然咱們在建立標籤的時候,用-a指定標籤名,-m指定說明文字: Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev) $ git tag -a v0.1 -m "add shell script" 15d01da Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev) $ git show v0.1
#標籤的刪除 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev) $ git tag -d v0.1 Deleted tag 'v0.1' (was e176957) #推送某個標籤到遠程,使用命令git push origin <tagname>: Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev) $ git push origin v1.0 #一次性推送所有還沒有推送到遠程的本地標籤: Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev) $ git push origin --tags #刪除遠程的標籤(先刪除本地,再刪除遠程): Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev) $ git tag -d v0.9 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev) $ git push origin :refs/tags/v0.9
已經在本地建立了一個Git倉庫後,又想在GitHub建立一個Git倉庫,而且讓這兩個倉庫進行遠程同步,這樣,GitHub上的倉庫既能夠做爲備份,又可讓其餘人經過該倉庫來協做,真是一舉多得。
#表示的是鏈接gitHub上的遠程倉庫 $ git remote add origin git@github.com:michaelliao/learngit.git
#把本地庫的全部內容推送到遠程庫上 $ git push -u origin master
用git push命令,其實是把當前分支master推送到遠程。因爲遠程庫是空的,咱們第一次推送master分支時,加上了-u參數,Git不但會把本地的master分支內容推送的遠程新的master分支,還會把本地的master分支和遠程的master分支關聯起來,在之後的推送或者拉取時就能夠簡化命令。當一次推送成功以後:只要本地做了提交,就能夠經過命令:
#此時咱們在遠程倉庫中有相應的數據,咱們想下載到本地倉庫: $ git clone git@github.com:ZZY478086819/test_repositort.git
這樣在本地的目錄中就要從遠程倉庫中克隆的文件。
注意:Git支持多種協議,包括https,但經過ssh支持的原生git協議速度最快。
當你從遠程倉庫克隆時,實際上Git自動把本地的master分支和遠程的master分支對應起來了,而且,遠程倉庫的默認名稱是origin。
#要查看遠程庫的信息,用git remote: Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev) $ git remote origin #用git remote -v顯示更詳細的信息: Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev) $ git remote -v origin git@github.com:ZZY478086819/test_repositort.git (fetch) origin git@github.com:ZZY478086819/test_repositort.git (push) #推送分支,就是把該分支上的全部本地提交推送到遠程庫。推送時,要指定本地分支,這樣,Git就會把該分支推送到遠程庫對應的遠程分支上: Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev) $ git push origin master(分支名,固然也能夠推送其餘的分支)
注意:
• master分支是主分支,所以要時刻與遠程同步;
• dev分支是開發分支,團隊全部成員都須要在上面工做,因此也須要與遠程同步;
• bug分支只用於在本地修復bug,就不必推到遠程了,除非老闆要看看你每週到底修復了幾個bug;
• feature分支是否推到遠程,取決於你是否和你的小夥伴合做在上面開發。
多人協做時,你們都會往master和dev分支上推送各自的修改,如今,模擬一個你的小夥伴,能夠在另外一臺電腦或者同一臺電腦的另外一個目錄下克隆。
#從遠端克隆 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_origin_test $ git clone git@github.com:ZZY478086819/test_repositort.git #查看本地分支,可是隻能看見master分支 Administrator@WIN10-901241016 MINGW64 /e/code_test/git_origin_test/test_repositort (master) $ git branch * master #如今要在dev分支上開發,就必須建立遠程origin的dev分支到本地,因而建立本地dev分支: Administrator@WIN10-901241016 MINGW64 /e/code_test/git_origin_test/test_repositort (master) $ git checkout -b dev origin/dev #在dev上繼續修改,而後,時不時地把dev分支push到遠程: Administrator@WIN10-901241016 MINGW64 /e/code_test/git_origin_test/test_repositort (dev) $ vim env.txt Administrator@WIN10-901241016 MINGW64 /e/code_test/git_origin_test/test_repositort (dev) $ git add env.txt warning: LF will be replaced by CRLF in env.txt. The file will have its original line endings in your working directory. Administrator@WIN10-901241016 MINGW64 /e/code_test/git_origin_test/test_repositort (dev) $ git commit -m "add env" Administrator@WIN10-901241016 MINGW64 /e/code_test/git_origin_test/test_repositort (dev) $ git push origin dev
#你的小夥伴已經向origin/dev分支推送了他的提交,而碰巧你也對一樣的文件做了修改,並試圖推送 $ cat env.txt env $ git add env.txt $ git commit -m "add new env" [dev 7bd91f1] add new env 1 file changed, 1 insertion(+) create mode 100644 env.txt $ git push origin dev To github.com:michaelliao/learngit.git ! [rejected] dev -> dev (non-fast-forward) error: failed to push some refs to 'git@github.com:ZZY478086819/test_repositort.git' hint: Updates were rejected because the tip of your current branch is behind hint: its remote counterpart. Integrate the remote changes (e.g. hint: 'git pull ...') before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help' for details.
推送失敗,由於你的小夥伴的最新提交和你試圖推送的提交有衝突,解決辦法也很簡單,Git已經提示咱們,先用git pull把最新的提交從origin/dev抓下來,而後,在本地合併,解決衝突,再推送:
$ git pull There is no tracking information for the current branch. Please specify which branch you want to merge with. See git-pull(1) for details. git pull <remote> <branch> If you wish to set tracking information for this branch you can do so with: git branch --set-upstream-to=origin/<branch> dev
git pull也失敗了,緣由是沒有指定本地dev分支與遠程origin/dev分支的連接,根據提示,設置dev和origin/dev的連接:
#git branch --set-upstream-to=origin/dev dev
再pull:
#git pull
這回git pull成功,可是合併有衝突,須要手動解決,解決的方法和分支管理中的解決衝突徹底同樣。解決後,提交,再push:
#解決衝突以後提交,並push $ git commit -m "fix env conflict" [dev 57c53ab] fix env conflict $ git push origin dev Counting objects: 6, done. Delta compression using up to 4 threads. Compressing objects: 100% (4/4), done. Writing objects: 100% (6/6), 621 bytes | 621.00 KiB/s, done. Total 6 (delta 0), reused 0 (delta 0) To git@github.com:ZZY478086819/test_repositort.git 7a5e5dd..57c53ab dev -> dev
總結:這裏出現衝突的緣由是,當你的同事修改代碼以後,進行push,此時dev分支已經被修改,可是你沒有獲得最新的修改後的dev分支的代碼,此時你的本地的版本庫中的最新的代碼和遠程倉庫中的不一致,致使了這次push失敗,因此你須要手動的將遠端的dev分支代碼pull下來,進行衝突解決,才能push。