先用一幅圖,從整體上描述主要git命令的工做流程css
workspace: 本地的工做目錄。(記做A)
index/stage:暫存區域,臨時保存本地改動。 (記做B)
local repository: 本地倉庫,只想最後一次提交HEAD。(記做C)
remote repository:遠程倉庫。(記做D)git
如下全部的命令的功能說明,都採用上述的標記的A、B、C、D的方式來闡述。github
初始化數據庫
git init //建立 git clone /path/to/repository //檢出 git config --global user.email "you@example.com" //配置email git config --global user.name "Name" //配置用戶名
操做segmentfault
git add <file> // 文件添加,A → B git add . // 全部文件添加,A → B git commit -m "代碼提交信息" //文件提交,B → C git commit --amend //與上次commit合併, *B → C git push origin master //推送至master分支, C → D git pull //更新本地倉庫至最新改動, D → A git fetch //抓取遠程倉庫更新, D → C git log //查看提交記錄 git status //查看修改狀態 git diff//查看詳細修改內容 git show//顯示某次提交的內容
撤銷操做安全
git reset <file>//某個文件索引會回滾到最後一次提交, C → B git reset//索引會回滾到最後一次提交, C → B git reset --hard // 索引會回滾到最後一次提交, C → B → A git checkout // 從index複製到workspace, B → A git checkout -- files // 文件從index複製到workspace, B → A git checkout HEAD -- files // 文件從local repository複製到workspace, C → A
分支相關網絡
git checkout -b branch_name //建立名叫「branch_name」的分支,並切換過去 git checkout master //切換回主分支 git branch -d branch_name // 刪除名叫「branch_name」的分支 git push origin branch_name //推送分支到遠端倉庫 git merge branch_name // 合併分支branch_name到當前分支(如master) git rebase //衍合,線性化的自動, D → A
衝突處理ssh
git diff //對比workspace與index git diff HEAD //對於workspace與最後一次commit git diff <source_branch> <target_branch> //對比差別 git add <filename> //修改完衝突,須要add以標記合併成功
其餘分佈式
gitk //開燈圖形化git git config color.ui true //彩色的 git 輸出 git config format.pretty oneline //顯示歷史記錄時,每一個提交的信息只顯示一行 git add -i //交互式添加文件到暫存區
① 建立版本庫
經過git init
命令把這個目錄變成Git能夠管理的倉庫
第一步,用命令git add告訴Git,把文件添加到倉庫:
$ git add readme.txt
執行上面的命令,沒有任何顯示,這就對了,ide
Unix的哲學是「沒有消息就是好消息」
說明添加成功。
第二步,用命令git commit -m "xxx"
告訴Git,把文件提交到倉庫,-m後面輸入的是本次提交的說明,能從歷史記錄裏方便地找到改動記錄。
② 添加遠程庫
git remote add origin git@github.com:tcyfree/test.git(或https://github.com/tcyfree/test.git,用git@比https快)
添加後,遠程庫的名字就是origin,這是Git默認的叫法,也能夠改爲別的,可是origin這個名字一看就知道是遠程庫。
下一步,就能夠把本地庫的全部內容推送到遠程庫上:
$ git push -u origin master
把本地庫的內容推送到遠程,用git push
命令,其實是把當前分支master推送到遠程。
因爲遠程庫是空的,咱們第一次推送master分支時,加上了-u參數,Git不但會把本地的master分支內容推送的遠程新的master分支,還會把本地的master分支和遠程的master分支關聯起來,在之後的推送或者拉取時就能夠簡化命令。
總結:從如今起,只要本地做了提交,就能夠經過命令:git push origin master
把本地master分支的最新修改推送至GitHub,如今,你就擁有了真正的分佈式版本庫!
要關聯一個遠程庫,使用命令git remote add origin git@server-name:path/repo-name.git;
關聯後,使用命令git push -u origin master第一次推送master分支的全部內容;
此後,每次本地提交後,只要有必要,就可使用命令git push origin master推送最新修改;
分佈式版本系統的最大好處之一是在本地工做徹底不須要考慮遠程庫的存在,也就是有沒有聯網均可以正常工做,而SVN在沒有聯網的時候是拒絕幹活的!當有網絡的時候,再把本地提交推送一下就完成了同步,真是太方便了!
③ 從遠程庫克隆
上次咱們講了先有本地庫,後有遠程庫的時候,如何關聯遠程庫。
如今,假設咱們從零開發,那麼最好的方式是先建立遠程庫,而後,從遠程庫克隆。
要克隆一個倉庫,首先必須知道倉庫的地址,而後使用git clone命令克隆。
Git支持多種協議,包括https,但經過ssh支持的原生git協議速度最快。
時光機穿梭
1.要隨時掌握工做區的狀態,使用git status
命令。
2.若是git status告訴你有文件被修改過,用git diff
能夠查看修改內容。
版本回退
1.HEAD指向的版本就是當前版本,所以,Git容許咱們在版本的歷史之間穿梭,使用命令git reset --hard commit_id
。
2.穿梭前,用git log
能夠查看提交歷史,以便肯定要回退到哪一個版本。
3.要重返將來,用git reflog
查看命令歷史,以便肯定要回到將來的哪一個版本。
git diff HEAD -- readme.txt命令能夠查看工做區和版本庫裏面最新版本的區別
撤銷修改
場景1:當你改亂了工做區某個文件的內容,想直接丟棄工做區的修改時,用命令git checkout -- file
。
場景2:當你不但改亂了工做區某個文件的內容,還添加到了暫存區時,想丟棄修改,分兩步,第一步用命令git reset HEAD file
,就回到了場景1,第二步按場景1操做。
(git reset
命令既能夠回退版本,也能夠把暫存區的修改回退到工做區。當咱們用HEAD時,表示最新的版本。)
場景3:已經提交了不合適的修改到版本庫時,想要撤銷本次提交,參考版本回退一節,不過前提是沒有推送到遠程庫。
刪除文件
1.命令git rm
用於刪除一個文件。
2.確實要從版本庫中刪除該文件,那就用命令git rm刪掉,而且git commit:
$ git rm test.txt rm 'test.txt' $ git commit -m "remove test.txt" [master d17efd8] remove test.txt 1 file changed, 1 deletion(-) delete mode 100644 test.txt
如今,文件就從版本庫中被刪除了
git checkout實際上是用版本庫裏的版本替換工做區的版本,不管工做區是修改仍是刪除,均可以「一鍵還原」。
git pull:至關因而從遠程獲取最新版本並merge到本地
git pull origin master
上述命令其實至關於git fetch 和 git merge
在實際使用中,git fetch更安全一些
由於在merge前,咱們能夠查看更新狀況,而後再決定是否合併
建立與合併分支
截止到目前,只有一條時間線,在Git裏,這個分支叫主分支,即master分支。HEAD嚴格來講不是指向提交,而是指向master,master纔是指向提交的,因此,HEAD指向的就是當前分支。
git checkout
命令加上-b
參數表示建立並切換,至關於如下兩條命令:
$ git branch dev $ git checkout dev Switched to branch 'dev'
而後,用git branch
命令查看當前分支:
$ git branch * dev master
git branch命令會列出全部分支,當前分支前面會標一個*
號。
假如咱們在dev上的工做完成了,就能夠把dev合併到master上。Git怎麼合併呢?最簡單的方法,就是直接把master指向dev的當前提交,就完成了合併:
因此Git合併分支也很快!就改改指針,工做區內容也不變!
合併完分支後,甚至能夠刪除dev分支。刪除dev分支就是把dev指針給刪掉,刪掉後,咱們就剩下了一條master分支:
git merge
命令用於合併指定分支到當前分支。合併後,再查看readme.txt的內容,就能夠看到,和dev分支的最新提交是徹底同樣的。
注意到上面的Fast-forward信息,Git告訴咱們,此次合併是「快進模式」,也就是直接把master指向dev的當前提交,因此合併速度很是快。
小結
Git鼓勵大量使用分支:
查看分支:git branch
建立分支:git branch <name>
切換分支:git checkout <name>
建立+切換分支:git checkout -b <name>
合併某分支到當前分支:git merge <name>
刪除分支:git branch -d <name>
解決衝突
Git用<<<<<<<,=======,>>>>>>>標記出不一樣分支的內容
修改master後提交:
如今,master分支和feature1分支變成了下圖所示:
最後,刪除feature1分支:
git branch -d feature1
總結:
當Git沒法自動合併分支時,就必須首先解決衝突。解決衝突後,再提交,合併完成。
用git log --graph
命令能夠看到分支合併圖。
分支管理策略
一般,合併分支時,若是可能,Git會用Fast forward模式,但這種模式下,刪除分支後,會丟掉分支信息。
分支策略
在實際開發中,咱們應該按照幾個基本原則進行分支管理:
首先,master分支應該是很是穩定的,也就是僅用來發布新版本,平時不能在上面幹活;
那在哪幹活呢?幹活都在dev分支上,也就是說,dev分支是不穩定的,到某個時候,好比1.0版本發佈時,再把dev分支合併到master上,在master分支發佈1.0版本;
你和你的小夥伴們每一個人都在dev分支上幹活,每一個人都有本身的分支,時不時地往dev分支上合併就能夠了。
因此,團隊合做的分支看起來就像這樣:
準備合併dev分支,請注意--no-ff參數,表示禁用Fast forward:
$ 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描述寫進去。
合併後,咱們用git log看看分支歷史:
$ git log --graph --pretty=oneline --abbrev-commit
7825a50 merge with no-ff
|\
| * 6224937 add merge
|/
59bc1cb conflict fixed
...
能夠看到,不使用Fast forward模式,merge後就像這樣:
小結
Git分支十分強大,在團隊開發中應該充分應用。
合併分支時,加上--no-ff參數就能夠用普通模式合併,合併後的歷史有分支,能看出來曾經作過合併,而fast forward合併就看不出來曾經作過合併。
Bug分支
修復bug時,咱們會經過建立新的bug分支進行修復,而後合併,最後刪除;
當手頭工做沒有完成時,先把工做現場git stash
一下,而後去修復bug,修復後,再git stash pop
,回到工做現場。
Feature分支
軟件開發中,總有無窮無盡的新的功能要不斷添加進來。
添加一個新功能時,你確定不但願由於一些實驗性質的代碼,把主分支搞亂了,因此,每添加一個新功能,最好新建一個feature分支,在上面開發,完成後,合併,最後,刪除該feature分支。
若是要丟棄一個沒有被合併過的分支,能夠經過git branch -D <name>
強行刪除。
多人協做
當你從遠程倉庫克隆時,實際上Git自動把本地的master分支和遠程的master分支對應起來了,而且,遠程倉庫的默認名稱是origin。
要查看遠程庫的信息,用git remote
或者,用git remote -v
顯示更詳細的信息。
並非必定要把本地分支往遠程推送,那麼,哪些分支須要推送,哪些不須要呢?
master分支是主分支,所以要時刻與遠程同步;
dev分支是開發分支,團隊全部成員都須要在上面工做,因此也須要與遠程同步;
bug分支只用於在本地修復bug,就不必推到遠程了,除非老闆要看看你每週到底修復了幾個bug;
feature分支是否推到遠程,取決於你是否和你的小夥伴合做在上面開發。
總之,就是在Git中,分支徹底能夠在本地本身藏着玩,是否推送,視你的心情而定!
多人協做的工做模式一般是這樣:
首先,能夠試圖用git push origin branch-name推送本身的修改;
若是推送失敗,則由於遠程分支比你的本地更新,須要先用git pull試圖合併;
若是合併有衝突,則解決衝突,並在本地提交;
沒有衝突或者解決掉衝突後,再用git push origin branch-name推送就能成功!
若是git pull
提示「no tracking information」
,則說明本地分支和遠程分支的連接關係沒有建立,用命令git branch --set-upstream branch-name origin/branch-name
。
小結
查看遠程庫信息,使用git remote -v
;
本地新建的分支若是不推送到遠程,對其餘人就是不可見的;
從本地推送分支,使用git push origin branch-name
,若是推送失敗,先用git pull
抓取遠程的新提交;
在本地建立和遠程分支對應的分支,使用git checkout -b branch-name origin/branch-name
,本地和遠程分支的名稱最好一致;
創建本地分支和遠程分支的關聯,使用git branch --set-upstream branch-name origin/branch-name
;
從遠程抓取分支,使用git pull,若是有衝突,要先處理衝突。
這就是多人協做的工做模式,一旦熟悉了,就很是簡單。
忽略特殊文件
有些時候,你必須把某些文件放到Git工做目錄中,但又不能提交它們,好比保存了數據庫密碼的配置文件啦,等等,每次git status
都會顯示Untracked files ...
,有強迫症的童鞋內心確定不爽。
在Git工做區的根目錄下建立一個特殊的.gitignore
文件,而後把要忽略的文件名填進去,Git就會自動忽略這些文件。
忽略文件的原則是:
忽略操做系統自動生成的文件,好比縮略圖等;
忽略編譯生成的中間文件、可執行文件等,也就是若是一個文件是經過另外一個文件自動生成的,那自動生成的文件就不必放進版本庫,好比Java編譯產生的.class文件;
忽略你本身的帶有敏感信息的配置文件,好比存放口令的配置文件。
加上你本身定義的文件,最終獲得一個完整的.gitignore文件,內容以下:
# Windows: Thumbs.db ehthumbs.db Desktop.ini # Python: *.py[cod] *.so *.egg *.egg-info dist build # My configurations: db.ini deploy_key_rsa
最後一步就是把.gitignore也提交到Git,就完成了!
小結
忽略某些文件時,須要編寫.gitignore
;
.gitignore
文件自己要放到版本庫裏,而且能夠對.gitignore
作版本管理!
安裝Git
參考文檔:Git經常使用命令
推薦文檔:Git經常使用命令和Git團隊使用規範指南
git - 簡易指南
經常使用Git命令清單