本文由雲+社區發表html
做者:工程師小熊linux
摘要:用了好久的Git和svn,因爲老是眼高手低,沒能靜下心來寫這些程序員平常開發最經常使用的知識點。如今準備開一個專題,專門來總結一下版本控制工具,讓咱們從git開始。完成本系列博客的閱讀之後,你將掌握git的基本概念與git的基本命令,能夠在本地爲所欲爲的完成代碼的提交撤銷保存修改等操做、能夠流暢的參與多人協做,本文致力於快速的入門,若是涉及到更高級的功能須要進行更深一步的學習。git
本文核心點:程序員
git是世界上目前最早進的分佈式版本控制系統,致力於團隊、我的進行項目版本管理,完美的解決難以比較代碼、難以合併代碼、難以取消修改、難以在寫當前代碼的過程當中保存未完成的修改去修改線上版本的bug等的痛點。github
git是一個很是強大的工具,但做爲一個git使用者來講,不用徹底學習Git的知識點與命令,由於有的命令的使用頻率很是的低甚至數年都不會用到,讓咱們來由淺入深進行學習。hexo
git是linux的創始人linus,在付費版本控制工具BitMover收回對Linux社區無償使用權利的時候,一怒之下花費兩個星期的時間寫出來的。(牛筆的人)app
選擇本身的操做系統對應的git版本安裝,安裝成功後運行git version
後,輸出git版本則安裝正確。編輯器
git 官方: https://git-scm.com/downloads分佈式
使用git config
命令來配置用戶名和郵箱svn
git config --global user.name "pzqu" git config --global user.email pzqu@example.com
若是用了 --global 選項,那麼更改的配置文件就是位於你用戶主目錄下的那個,之後你全部的項目都會默認使用這裏配置的用戶信息。若是要在某個特定的項目中使用其餘名字或者電郵,只要去掉 --global選項從新配置便可,新的設定保存在當前項目的 .git/config 文件裏。
使用git config user.name
和git config user.email
來檢查是否成功,也能夠直接用git config --list
來列出所有git配置信息來查看
假如咱們建立一個項目叫make_money,先建立一個文件夾叫make_money,再使用git init
命令建立git項目。
# pzqu @ pzqu-pc in ~/Documents/code/test [0:05:29] $ mkdir make_money # pzqu @ pzqu-pc in ~/Documents/code/test [0:06:24] $ ls make_money # pzqu @ pzqu-pc in ~/Documents/code/test [0:06:29] $ cd make_money # pzqu @ pzqu-pc in ~/Documents/code/test/make_money [0:07:10] $ git init Initialized empty Git repository in /Users/pzqu/Documents/code/test/make_money/.git/ # pzqu @ pzqu-pc in ~/Documents/code/test/make_money on git:master o [0:07:12] $ ls -al total 0 drwxr-xr-x 3 pzqu staff 96 11 7 00:07 . drwxr-xr-x 3 pzqu staff 96 11 7 00:06 .. drwxr-xr-x 9 pzqu staff 288 11 7 00:07 .git
建立成功之後,會出現一個叫.git的隱藏文件夾,這個就是你的git倉庫,之後全部的git操做歷史提交記錄信息就所有記錄在此了,只要這個文件夾在就能夠記住咱們的所有git操做
在使用git的時候還要清楚暫存區和工做區的含義,參考廖雪峯的官方網站-git篇-工做區和暫存區
# pzqu @ pzqu-pc in ~/Documents/code/test/git_test on git:master o [11:37:50] $ ls README.md # pzqu @ pzqu-pc in ~/Documents/code/test/git_test on git:master o [11:42:02] $ touch file1.txt # pzqu @ pzqu-pc in ~/Documents/code/test/git_test on git:master x [11:42:15] $ git add file1.txt # pzqu @ pzqu-pc in ~/Documents/code/test/git_test on git:master x [11:42:23] $ git status On branch master Your branch is up to date with 'origin/master'. Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: file1.txt # pzqu @ pzqu-pc in ~/Documents/code/test/git_test on git:master x [11:56:38] $ git commit -m "[+]add new file1.txt" [master 66cc488] [+]add new file1.txt 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 file1.txt
上圖操做包含:
git add .
:監控工做區的狀態樹,此命令會把工做時的全部變化提交到暫存區,包括文件內容修改(modified)以及新文件(new),但不包括被刪除的文件。
git add -u
:他僅監控已經被add的文件(即tracked file),他會將被修改的文件提交到暫存區。add -u 不會提交新文件(untracked file)。(git add --update的縮寫)
git add -A
:是上面兩個功能的合集(git add --all的縮寫)
upload successful
git show 列出最近一次的提交
對於commit:像這樣,你不斷對文件進行修改,而後不斷提交修改到版本庫裏,就比如玩RPG遊戲時,每經過一關就會自動把遊戲狀態存盤,若是某一關沒過去,你還能夠選擇讀取前一關的狀態。有些時候,在打Boss以前,你會手動存盤,以便萬一打Boss失敗了,能夠從最近的地方從新開始。Git也是同樣,每當你以爲文件修改到必定程度的時候,就能夠「保存一個快照」,這個快照在Git中被稱爲commit。一旦你把文件改亂了,或者誤刪了文件,還能夠從最近的一個commit恢復,而後繼續工做,而不是把幾個月的工做成果所有丟失。
# pzqu @ pzqu-pc in ~/Documents/code/test/git_test on git:master o [12:55:24] $ ls README.md file1.txt # pzqu @ pzqu-pc in ~/Documents/code/test/git_test on git:master o [12:55:25] $ git rm file1.txt rm 'file1.txt' # pzqu @ pzqu-pc in ~/Documents/code/test/git_test on git:master x [12:55:30] $ ls README.md # pzqu @ pzqu-pc in ~/Documents/code/test/git_test on git:master x [12:55:32] $ git status On branch master Your branch is ahead of 'origin/master' by 1 commit. (use "git push" to publish your local commits) Changes to be committed: (use "git reset HEAD <file>..." to unstage) deleted: file1.txt # pzqu @ pzqu-pc in ~/Documents/code/test/git_test on git:master x [12:55:40] C:128 $ git commit -m "[-]delete file1.txt" [master e278392] [-]delete file1.txt 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 file1.txt
上圖操做包含:
tip1: 若是沒有用git rm刪除文件,在本地刪除文件後,git add一下再提交能夠達到一樣的效果
tip2: 要是你加班太晚,頭暈不當心刪除了不想刪除的文件怎麼辦?見
下一篇:版本控制工具——Git經常使用操做(下)-後悔藥
# pzqu @ pzqu-pc in ~/Documents/code/test/git_test on git:master o [17:01:13] $ git pull remote: Enumerating objects: 4, done. remote: Counting objects: 100% (4/4), done. remote: Compressing objects: 100% (2/2), done. remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 Unpacking objects: 100% (3/3), done. From github.com:pzqu/git_test 5fd4d8f..7b54a8a master -> origin/master Merge made by the 'recursive' strategy. share_file.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 share_file.txt
上圖命令:
查看本地倉庫變化git log
upload successful
上圖能夠看到向遠程倉庫pull的時候,出現了兩個新的commit,commit 7b54a8ae74...
的提交信息爲Create share_file.txt
,另外一個commit fdbb19cf4c51770
的提交信息爲Merge branch 'master' of github.com:pzqu/git_test
。事實上主線只有一個提交,爲何會出現這種狀況? 是由於pull其實會作兩個操做
注意這裏的第二個個步驟若是遠程有人和你改了同一個文件就會出現一個衝突,這個時候git會提示你哪些文件有衝突,手動改了再提交一次就能夠了。詳情見合併衝突
我在遠程修改了文件,向share_file.txt
加了一行內容tom modify
,此時拉代碼。
# pzqu @ pzqu-pc in ~/Documents/code/test/git_test on git:master o [21:07:21] $ git fetch # pzqu @ pzqu-pc in ~/Documents/code/test/git_test on git:master o [21:08:43] $ git rebase origin/master First, rewinding head to replay your work on top of it... Applying: [+]add new file1.txt Applying: [-]delete file1.txt
上圖所示有如下兩個操做
效果以下:
upload successful
上圖是git log
所輸出的提交內容,剛剛pull的時候忘記把pull自動產生的merge提交到遠程,rebase的時候把本地的提交放到了遠程提交以後,看起來就是一條直線,比較優雅,也是推薦的方式。
一樣的,若是產生了衝突,詳情見合併衝突
分支是多人協同最經典的地方所在,咱們來建立一個分支
$ git checkout -b dev/pzqu origin/master Branch 'dev/pzqu' set up to track remote branch 'master' from 'origin'. Switched to a new branch 'dev/pzqu' $ git branch * dev/pzqu master
git checkout -b 分支名 其餘分支
,-b
表明建立並切換到新建的分支,分支名
表明新建立的分支叫什麼名字,這裏叫dev/pzqu
,其餘分支
表明基於哪個分支來建立,這裏基於遠程的master分支origin/master
,若是省略則表明基於當前分支git branch
展現本地的分支狀況,加-a
參數能夠展現所有的分支,包括遠程分支*
在分支前,指明瞭如今所在的分支是dev/pzqu
$ git checkout -b dev/pzqu2 Switched to a new branch 'dev/pzqu2' $ git branch dev/pzqu * dev/pzqu2 master $ git checkout dev/pzqu Switched to branch 'dev/pzqu' Your branch is up to date with 'origin/master'. $ git branch * dev/pzqu dev/pzqu2 master
dev/pzqu2
git checkout 已存在的分支名
切換分支回到dev/pzqu
$ git branch * dev/pzqu dev/pzqu2 master $ git branch -D dev/pzqu2 Deleted branch dev/pzqu2 (was 7c9be37). $ git branch * dev/pzqu master
dev/pzqu
,刪除了dev/pzqu2
分支爲了產生一個衝突,我在另外一個地方向遠程倉庫提交了代碼,更改share_file.txt
文件,加了一行內容tom add for merge
,
本地修改同一個文件加了一行pzqu add for merge
,並提交到本地,這樣一來,本地和遠程倉庫的同一個文件就不同了,一會拉代碼必定會產生一個衝突。效果以下:
upload successful
upload successful
Git用<<<<<<<
,=======
,>>>>>>>
標記出不一樣分支的內容,咱們修改以下後保存:
upload successful
git add
再git rebase --continue
後完成rebase,效果以下,再push
的遠程倉庫便可
upload successful
關於怎麼建立分支與切換分支見建立分支和切換分支,這裏只討論合併時產生的衝突的狀況,咱們已經基於master
分支建立了一個dev/pzqu
分支
$ git branch * dev/pzqu master
切換到master
分支,加一行master add for merge
並提交,文件內容以下:
$ cat share_file.txt tom add tom modify tom add for merge pzqu add for merge master add for merge
切換到dev/pzqu
分支,向share_file.txt
加入一行dev/pzqu add for merge
並提交,如今share_file.txt
內容以下:
$ cat share_file.txt tom add tom modify tom add for merge pzqu add for merge dev/pzqu add for merge
如今兩個分支的同一個文件內容不同了,如今咱們在dev/pzqu
分支上進行合併:
$ git merge master Auto-merging share_file.txt CONFLICT (content): Merge conflict in share_file.txt Automatic merge failed; fix conflicts and then commit the result. # pzqu @ pzqu-pc in ~/Documents/code/test/git_test on git:dev/pzqu x [11:17:31] C:1 $ git status On branch dev/pzqu Your branch is ahead of 'origin/master' by 1 commit. (use "git push" to publish your local commits) 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: share_file.txt no changes added to commit (use "git add" and/or "git commit -a") $ cat share_file.txt tom add tom modify tom add for merge pzqu add for merge <<<<<<< HEAD dev/pzqu add for merge ======= master add for merge >>>>>>> master
上圖出現了一個衝突,是咱們意料之中的,修改share_file.txt
文件,解決此衝突:
$ cat share_file.txt tom add tom modify tom add for merge pzqu add for merge dev/pzqu add for merge master add for merge $ git add share_file.txt # pzqu @ pzqu-pc in ~/Documents/code/test/git_test on git:dev/pzqu x [11:22:40] $ git commit -m "[*]merge master to dev/pzqu" [dev/pzqu d9e018e] [*]merge master to dev/pzqu # pzqu @ pzqu-pc in ~/Documents/code/test/git_test on git:dev/pzqu o [11:23:00] $ git status On branch dev/pzqu Your branch is ahead of 'origin/master' by 3 commits. (use "git push" to publish your local commits) nothing to commit, working tree clean
衝突解決也提交了,看看咱們如今的分支內容:
upload successful
上圖咱們能夠看到:
master
分支比遠程origin/master
分支多一次提交,dev/pzqu
分支因爲是基於origin/master
分支,合併了master
分支的提交和當前dev/pzqu
分支的提交,超出本地master
兩個提交,致此咱們把master
合併到dev/pzqu
的操做就完成了。dev/pzqu
合併到master
分支,而後把兩個分支都提交到遠程。$ git checkout master Switched to branch 'master' Your branch is ahead of 'origin/master' by 1 commit. (use "git push" to publish your local commits) $ git merge dev/pzqu Updating 58f047a..d9e018e Fast-forward share_file.txt | 1 + 1 file changed, 1 insertion(+) $ git push origin master Total 0 (delta 0), reused 0 (delta 0) To github.com:pzqu/git_test.git 7c9be37..d9e018e master -> master $ git push origin dev/pzqu Counting objects: 9, done. Delta compression using up to 8 threads. Compressing objects: 100% (9/9), done. Writing objects: 100% (9/9), 887 bytes | 887.00 KiB/s, done. Total 9 (delta 2), reused 0 (delta 0) remote: Resolving deltas: 100% (2/2), done. remote: remote: Create a pull request for 'dev/pzqu' on GitHub by visiting: remote: https://github.com/pzqu/git_test/pull/new/dev/pzqu remote: To github.com:pzqu/git_test.git * [new branch] dev/pzqu -> dev/pzqu
master
分支dev/pzqu
到master
分支master
推到遠程倉庫dev/pzqu
要保留,就能夠推送到遠程倉庫。upload successful
這種狀況通常是出如今你正在完成一個功能,可是突然線上發現了一個Bug,必須立刻開一個新的分支來修復bug,可是如今的功能沒寫完不打算提交(commit),如今怎麼辦??不用怕暫存代碼來幫助你。
$ git status On branch dev/pzqu Your branch is up to date with 'origin/master'. Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: need_stash.txt modified: share_file.txt $ git stash Saved working directory and index state WIP on dev/pzqu: d9e018e [*]merge master to dev/pzqu $ git stash list stash@{0}: WIP on dev/pzqu: d9e018e [*]merge master to dev/pzqu $ git status On branch dev/pzqu Your branch is up to date with 'origin/master'. nothing to commit, working tree clean //省略操做:去建立一個Bug分支,修復他並完成與主線的合併,刪除Bug分支。 //省略操做:切回來當前分支繼續開發 //下面來恢復現場 $ git stash apply stash@{0} On branch dev/pzqu Your branch is up to date with 'origin/master'. Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: need_stash.txt 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: share_file.txt
status
查看到有2個文件修改沒有提交stash
把修改放到暫存區,並生成一個idstash list
列出暫存區全部內容stash apply
從新把暫存區內容放到本地這裏的stash apply
成功的把暫存區的一次暫存恢復到了本地,可是暫存區還有會保存此次暫存,若是想刪除此次暫存要用git stash drop
來刪除;也能夠用git stash pop
,恢復最後一次暫存的同時把stash內容也刪了。
$ git stash drop stash@{0} Dropped stash@{0} (bfdc065df8adc44c8b69fa6826e75c5991e6cad0) $ git stash list
好了,暫存區清乾淨了。
注意:要放到暫存區的文件必定要先經過git add加到index
本文閱讀結束之後,咱們學會了
Git經常使用操做(下)我計劃給你們介紹如下點:
理論上,git平常用到的命令是 diff show fetch rebase pull push checkout commit status 等,這些命令都不會致使代碼丟失,假如懼怕代碼丟失,能夠預先commit一次,再進行修改,但切記
不可以使用本身不熟悉的命令 任何命令,不要加上-f的強制參數,不然可能致使代碼丟失
建議多使用命令行,不要使用圖形界面操做
此文已由騰訊雲+社區在各渠道發佈
獲取更多新鮮技術乾貨,能夠關注咱們騰訊雲技術社區-雲加社區官方號及知乎機構號