版本控制工具——Git經常使用操做(上)

本文由雲+社區發表html

做者:工程師小熊linux

摘要:用了好久的Git和svn,因爲老是眼高手低,沒能靜下心來寫這些程序員平常開發最經常使用的知識點。如今準備開一個專題,專門來總結一下版本控制工具,讓咱們從git開始。完成本系列博客的閱讀之後,你將掌握git的基本概念與git的基本命令,能夠在本地爲所欲爲的完成代碼的提交撤銷保存修改等操做、能夠流暢的參與多人協做,本文致力於快速的入門,若是涉及到更高級的功能須要進行更深一步的學習。git

本文核心點:程序員

  • Git的基本概念
  • 一我的使用Git時的代碼版本控制--(提交、拉代碼、分支操做)
  • 多人合做時的代碼版本控制--(合併衝突、暫存代碼)

什麼是Git

簡介

git是世界上目前最早進的分佈式版本控制系統,致力於團隊、我的進行項目版本管理,完美的解決難以比較代碼、難以合併代碼、難以取消修改、難以在寫當前代碼的過程當中保存未完成的修改去修改線上版本的bug等的痛點。github

git是一個很是強大的工具,但做爲一個git使用者來講,不用徹底學習Git的知識點與命令,由於有的命令的使用頻率很是的低甚至數年都不會用到,讓咱們來由淺入深進行學習。hexo

git的歷史

git是linux的創始人linus,在付費版本控制工具BitMover收回對Linux社區無償使用權利的時候,一怒之下花費兩個星期的時間寫出來的。(牛筆的人)app

開始

安裝git

選擇本身的操做系統對應的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.namegit config user.email來檢查是否成功,也能夠直接用git config --list來列出所有git配置信息來查看

img

建立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

上圖操做包含:

  • 建立新文件file1.txt
  • add 添加修改的內容到索引
  • status 查看修改的內容
  • commit 把索引提交到本地分支

git add . :監控工做區的狀態樹,此命令會把工做時的全部變化提交到暫存區,包括文件內容修改(modified)以及新文件(new),但不包括被刪除的文件。

git add -u:他僅監控已經被add的文件(即tracked file),他會將被修改的文件提交到暫存區。add -u 不會提交新文件(untracked file)。(git add --update的縮寫)

git add -A :是上面兩個功能的合集(git add --all的縮寫)

imgupload 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

上圖操做包含:

  • 建立新文件file1.txt
  • git rm 刪除file1.txt文件
  • status 查看修改的內容
  • commit 把索引提交到本地分支

tip1: 若是沒有用git rm刪除文件,在本地刪除文件後,git add一下再提交能夠達到一樣的效果

tip2: 要是你加班太晚,頭暈不當心刪除了不想刪除的文件怎麼辦?見

下一篇:版本控制工具——Git經常使用操做(下)-後悔藥

拉代碼

方法一 pull

# 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 pull

查看本地倉庫變化git log

imgupload successful

上圖能夠看到向遠程倉庫pull的時候,出現了兩個新的commit,commit 7b54a8ae74...的提交信息爲Create share_file.txt,另外一個commit fdbb19cf4c51770的提交信息爲Merge branch 'master' of github.com:pzqu/git_test。事實上主線只有一個提交,爲何會出現這種狀況? 是由於pull其實會作兩個操做

  • 拉遠程倉庫代碼到本地
  • 自動與當前分支合併並生成一個合併成功的提交

注意這裏的第二個個步驟若是遠程有人和你改了同一個文件就會出現一個衝突,這個時候git會提示你哪些文件有衝突,手動改了再提交一次就能夠了。詳情見合併衝突

方法二 fetch

我在遠程修改了文件,向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

上圖所示有如下兩個操做

  • fetch 拉取遠端代碼到本地
  • rebase 把本地代碼提交基於遠端分支從新replay

效果以下:

imgupload 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,並提交到本地,這樣一來,本地和遠程倉庫的同一個文件就不同了,一會拉代碼必定會產生一個衝突。效果以下:

imgupload successful

  • 通常rebase或pull衝突的時候,都會出現提示,而後git status會出現上圖圖示
  • 這個時候不能夠進行任何分支切換和commit操做,按照他提示進行處理
  • git status提示哪一個文件是都被修改的,both modified,而後使用編輯器修改該文件,解決衝突
  • 解決完成後,git add 添加該衝突文件
  • git rebase --continue,並更新commit message,完成整個rebase流程 咱們來看看這個衝突的文件:

imgupload successful

Git用<<<<<<<=======>>>>>>>標記出不一樣分支的內容,咱們修改以下後保存:

imgupload successful

git addgit rebase --continue後完成rebase,效果以下,再push的遠程倉庫便可

imgupload 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

衝突解決也提交了,看看咱們如今的分支內容:

imgupload 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/pzqumaster分支
  • master推到遠程倉庫
  • 若是dev/pzqu要保留,就能夠推送到遠程倉庫。

imgupload 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把修改放到暫存區,並生成一個id
  • stash 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的做用、歷史;學會安裝配置Git,使用Git建立項目託管以及工做區和暫存區的概念
  • 學會Git的本地操做,提交、拉代碼、建立切換刪除分支操做,
  • 多人合做時的代碼版本控制,學會了不一樣狀況下的合併衝突、暫存代碼操做

下集預告

Git經常使用操做(下)我計劃給你們介紹如下點:

  • 後悔藥-各類後悔操做(撤消commit,回滾,回退遠程倉庫等)
  • 哎呀,提交的時候漏了文件
  • tag操做
  • git忽略不想提交的文件

注意事項

理論上,git平常用到的命令是 diff show fetch rebase pull push checkout commit status 等,這些命令都不會致使代碼丟失,假如懼怕代碼丟失,能夠預先commit一次,再進行修改,但切記

不可以使用本身不熟悉的命令 任何命令,不要加上-f的強制參數,不然可能致使代碼丟失

建議多使用命令行,不要使用圖形界面操做

引用

git官網

廖雪峯的官方網站-git篇

hexo博客部署到vps

此文已由騰訊雲+社區在各渠道發佈

獲取更多新鮮技術乾貨,能夠關注咱們騰訊雲技術社區-雲加社區官方號及知乎機構號

相關文章
相關標籤/搜索