git學(xué)習(xí)筆記
聲明
本文是本人學(xué)習(xí)Git過程中所做的筆記,以便日后查閱,文中多有錯(cuò)漏之處,不建議用作學(xué)習(xí)材料,文章內(nèi)容來自網(wǎng)絡(luò),如需學(xué)習(xí)請移步原文:
Git教程-廖雪峰的官網(wǎng)網(wǎng)站
Git遠(yuǎn)程操作講解-阮一峰的網(wǎng)絡(luò)日志
Git誕生
2002年BitMover授權(quán)Linux社區(qū)免費(fèi)使用BitKeeper版本控制系統(tǒng)
2005年有人試圖破解BitKeeper的協(xié)議導(dǎo)致BitMover要收回Linux社區(qū)的使用權(quán)限
Linus花費(fèi)兩周時(shí)間使用C語言寫了一個(gè)分布式版本控制系統(tǒng),即git
集中式&分布式
什么是集中式版本控制系統(tǒng)
- 集中式版本控制系統(tǒng)的版本庫統(tǒng)一存放在中央服務(wù)器,每次編程時(shí)都要先從中央服務(wù)器取得最新版本,完成后再把自己的版本推送給服務(wù)器
- 缺陷:需要聯(lián)網(wǎng)才能工作
分布式版本控制系統(tǒng)(distributed version control system)
分布式版本控制系統(tǒng)沒有中央服務(wù)器,每臺(tái)電腦都是一個(gè)完整的版本庫,可以通過推送獲取最新版本
-
優(yōu)點(diǎn):
- 沒有中央服務(wù)器,不需要聯(lián)網(wǎng)
通常分布式版本控制系統(tǒng)中有一臺(tái)充當(dāng)服務(wù)器的電腦,方便交換大家的修改
- 安全性高:每個(gè)人的電腦都是版本庫
- Git的分支管理功能強(qiáng)大(branch)
安裝git
git命令可以查看系統(tǒng)有沒有安裝git
$ git
usage: git [--version] [--help] [-C <path>] [-c name=value]
[--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
[-p | --paginate | --no-pager] [--no-replace-objects] [--bare]
[--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
<command> [<args>]
Linux系統(tǒng)安裝
- Linux 使用命令即可直接安裝
sudo apt-get install git
Windows上安裝git
- Windows上安裝git需要通過模擬Linux運(yùn)行環(huán)境來完成,這里直接使用msysgit下載地址
至此Git的安裝已經(jīng)完成,下面是Git的學(xué)習(xí)階段
Git學(xué)習(xí)-版本庫
什么是版本庫
版本庫(Repository)又名倉庫,倉庫里的文件都可以由git管理起來,git會(huì)對每個(gè)文件的修改刪除進(jìn)行跟蹤,一遍將來的某個(gè)時(shí)刻可以還原-
創(chuàng)建版本庫
創(chuàng)建版本庫只需要?jiǎng)?chuàng)建一個(gè)文件夾然后通知Git講次文件夾作為倉庫管理$ mkdir gitlearn $ cd gitlearn $ pwd /c/Users/lc/learngit //創(chuàng)建git文件夾 $ git init Initialized empty Git repository in C:/Users/lc/learngit/.git/
版本控制系統(tǒng)只能跟蹤文本的改動(dòng),不能跟蹤文本的內(nèi)容,Microsoft Word的格式是二進(jìn)制的,版本控制系統(tǒng)無法跟蹤改動(dòng)
Git學(xué)習(xí)-版本提交
- 版本提交分為兩步
- 用
git add <file>
命令把文件添加到暫存區(qū) - 用
git commit
命令告知Git,將文件提交到倉庫
$ git commit -m "wrote a readme file"
//-m 命令是對本次提交的說明,輸入本次提交的內(nèi)容
- 用
Git學(xué)習(xí)-時(shí)空穿梭
git status
命令可以查看是否有文件被修改過
git status 主要用于查看倉庫當(dāng)前狀態(tài),比如哪些文件被修改,是否準(zhǔn)備提交
git diff
可以查看修改的內(nèi)容
只限于文件被添加到暫存區(qū)之前,一旦執(zhí)行了
git add
命令,git diff
就不能查看更改了
git diff 常用的命令
HEAD commit版本
Index staged版本
git diff//比較工作目錄和暫存區(qū)快照之間的差異
//即修改單還沒有暫存的內(nèi)容
git diff --cached
git diff --staged
//未發(fā)現(xiàn)區(qū)別
git diff HEAD
//顯示工作版本(work tree)和HEAD之間的查表
git diff topic master
git diff topic..master
//顯示兩個(gè)分支最新提交的區(qū)別
git diff HEAD^ HEAD
//顯示上次提交commit和上上次提交之間的差別
git add
的各種區(qū)別
git add -A // 添加所有改動(dòng)
git add * // 添加新建文件和修改,但是不包括刪除
git add . // 添加新建文件和修改,但是不包括刪除
git add -u // 添加修改和刪除,但是不包括新建文件
在commit前撤銷add:
git reset <file> // 撤銷提交單獨(dú)文件
git reset // unstage all due changes
add/commit前撤銷對文件的修改:
git checkout -- README.md // 注意, add添加后(同commit提交后)就無法通過這種方式撤銷修改
Git學(xué)習(xí)-版本回退
查看歷史記錄:
$ git log
//長串的編碼是commit id(版本號)
commit 75d2bf408c157c0b5c9255f81a6dd7116670f1cb
Author: Shenglong <liushenglong@wemarklinks.com>
Date: Tue Jun 27 11:45:28 2017 +0800
2.0 version
commit 2b9e2e1c667378bf00662c173d70581724d53bd0
Author: Shenglong <liushenglong@wemarklinks.com>
Date: Tue Jun 27 11:13:53 2017 +0800
find some Syntax Error
commit b193cdc3b9951c23279d45e04aed326ec3a866c5
Author: Shenglong <liushenglong@wemarklinks.com>
Date: Tue Jun 27 09:52:12 2017 +0800
test git
Git中 HEAD表示當(dāng)前版本,HEAD表示上一個(gè)版本,HEAD^ 表示上上個(gè)版本
HEAD~100表示向上100個(gè)版本
版本回退git reset
$ git reset --hard HEAD^
HEAD is now at 2b9e2e1 find some Syntax Error
//已經(jīng)回退到上一個(gè)版本
再來查看版本庫的狀態(tài)
$ git log
commit 2b9e2e1c667378bf00662c173d70581724d53bd0
Author: Shenglong <liushenglong@wemarklinks.com>
Date: Tue Jun 27 11:13:53 2017 +0800
find some Syntax Error
commit b193cdc3b9951c23279d45e04aed326ec3a866c5
Author: Shenglong <liushenglong@wemarklinks.com>
Date: Tue Jun 27 09:52:12 2017 +0800
test git
回退了一個(gè)版本,可以通過之前的版本id恢復(fù)版本或者繼續(xù)回退
$ git reset --hard 75d2bf408c
查看readme.txt內(nèi)容
$ cat readme.txt
git is a distributed version control System
i'm alittle confuse about how this worked
git is free software
版本回退的原理:Git內(nèi)部有一個(gè)指向當(dāng)前版本的HEAD指針,回退版本的時(shí)候git僅僅是把指針前移了一位
后悔藥:git reflog
,回退一個(gè)版本之后如果想退回原來的版本必須使用之前版本的commit id,然后使用git reset --hard commit id
即可返回最新提交的版本
Git學(xué)習(xí)-工作區(qū)與暫存區(qū)
工作區(qū)(Working Directory)工作目錄
版本庫(Repository)工作區(qū)有一個(gè)隱藏目錄,版本庫中包含stage(暫存區(qū)也可以稱為Index),以及Git創(chuàng)建的第一個(gè)分支master,以及指向master的一個(gè)指針HEAD
Git學(xué)習(xí)-管理修改
git commit
的作用是將暫存區(qū)中的修改應(yīng)用到版本庫中,未提交到暫存區(qū)的修改不會(huì)保存
git diff HEAD --readme.txt
可以查看工作區(qū)里和版本庫里最新版本的區(qū)別
Git學(xué)習(xí)-撤銷修改
在修改未被提交到工作區(qū)之前可以使用git checkout -- <file>
命令丟棄工作區(qū)的修改
exam:
$ cat readme.txt
git is a distributed version control System
i'm alittle confuse about how this worked
git is free software
git is full of fun!
wrong message(i don't wanna this to be commit)
//我在這里犯了個(gè)錯(cuò)誤,但是修改還沒有被提交到暫存區(qū)
//于是..
$ git checkout -- readme.txt
//這里看起來什么都沒有發(fā)生
$ cat readme.txt
git is a distributed version control System
i'm alittle confuse about how this worked
git is free software
git is full of fun!
//但是我錯(cuò)誤的修改已經(jīng)被丟棄了
如果修改被提交到暫存區(qū),可以使用git reset
丟棄暫存區(qū)的記錄回到上一步,然后丟棄工作區(qū)的記錄即可
Git學(xué)習(xí)-刪除文件
如果不小心刪除了工作區(qū)的文件,git status
查看時(shí)git 會(huì)告訴你哪些文件被刪除了
$ 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")
此時(shí)有兩個(gè)選擇:
-
從版本庫中刪除改文件
$ git rm test.txt rm test.txt $ git commit $ git commit [master 502080a] test.txt has been removed 1 file changed, 1 deletion(-) delete mode 100644 test.txt //此時(shí)版本庫和文件系統(tǒng)中都沒有test.txt了
git checkout -- <file>
如果誤刪了文件可以使用這個(gè)命令,用版本庫中的版本替換工作區(qū)中的版本
> `git checkout`命令本質(zhì)是從版本去檢出版本替換掉工作區(qū)的版本,雖然可以將文件恢復(fù)到最新版本,但是會(huì)丟失最近修改的內(nèi)容
遠(yuǎn)程倉庫
準(zhǔn)備工作
-
創(chuàng)建SSH Key
$ ssh-keygen -t rsa -C "email@url.com" Your identification has been saved in /c/Users/lc/.ssh/id_rsa. Your public key has been saved in /c/Users/lc/.ssh/id_rsa.pub. The key fingerprint is: SHA256:R0Qr3PkLDR7RD4Xrn1pUWrzo+TpA+tusnr0eMYT3qB4 liushenglong@wemarklinks.com The key's randomart image is: +---[RSA 2048]----+ | .+. o. | | . o += . | | o B. * +| | + *+ =+.| | S *.o=oo | | o o+o+ | | .Eo=.. | | ..*o= | | .*=O+. | +----[SHA256]-----+
登錄GitHub(Gitlab),進(jìn)入Account setting,"SSH Key"頁面,在Add SSH Key中填入id_rsa.pub中的內(nèi)容
添加遠(yuǎn)程庫
在git上創(chuàng)建庫 new Repository
-
在本地添加遠(yuǎn)程庫
$ git remote add origin https://GitHub.com/Sakura3754/learngit.git //把本地庫推送到遠(yuǎn)程庫上 $ git push -u origin master //第一次向遠(yuǎn)程庫推送時(shí)使用了-u參數(shù).Git不但把本地的master分支推送到遠(yuǎn)程新的master分支,還會(huì)把本地的master分支和遠(yuǎn)程的master分支關(guān)聯(lián)起來
提交完成
- 從現(xiàn)在起,只要本地做了提交就可以通過
git push origin master
提交到遠(yuǎn)程庫
從遠(yuǎn)程庫克隆
git clone git@github.com:Sakura3754/gitskills.git
分支管理
分支就是科幻電影里面的平行宇宙,當(dāng)你正在電腦前努力學(xué)習(xí)Git的時(shí)候,另一個(gè)你正在另一個(gè)平行宇宙里努力學(xué)習(xí)SVN。
創(chuàng)建與合并分支
每次提交,git將操作記錄串成一條時(shí)間線,這條時(shí)間線是一個(gè)分支,在git里這個(gè)分支叫主分支,即master分支.嚴(yán)格來說HEAD不是指向commit,而是指向master,master才是指向commit的
當(dāng)我們創(chuàng)建分支,例如dev
時(shí),Git新建一個(gè)指針叫dev
,指向master
相同的提交,再把HEAD
指向dev
就表示當(dāng)前分支在dev上
從現(xiàn)在開始,對工作區(qū)的修改和提交就是針對dev分支了,比如新提交一次后,dev
指針往前移動(dòng)一步,master
指針不變
合并分支:將master
指向dev當(dāng)前的提交就完成了分支的合并
刪除分支就是把指針刪除掉
實(shí)戰(zhàn):
-
創(chuàng)建分支
$ git checkout -b dev//-b 表示創(chuàng)建并切換
Switched to a new branch 'dev'
//上面的命令等價(jià)于
git branch dev//創(chuàng)建分支
git checkout dev//切換分支 git branch
查看當(dāng)前分支
- 創(chuàng)建分支`git branch dev`
- 切換分支`git checkout dev`
- 創(chuàng)建并切換分支`git checkout -b dev`
- 查看當(dāng)前分支`git branch`
- 合并分支到當(dāng)前分支`git merge dev`
- 刪除分支`git branch -d dev`
- 合并沖突時(shí)必須手動(dòng)解決之后再提交
分支管理
- 如果使用Fast forword 模式合并分支,刪除分支后會(huì)丟掉分支信息,可以使用
--no-ff
參數(shù)禁用fast forword
模式
> 使用no-ff模式提交時(shí),由于master不能直接將指針指向dev分支的最新提交,所以master分支只能獨(dú)立進(jìn)行一次提交操作,因此有內(nèi)容一樣,但是commit id不同的問題
- 分支管理原則:
* `master`分支應(yīng)該是非常穩(wěn)定的,僅用來發(fā)布新版本,不能在上面干活
* 所有的操作都在`dev`分支上進(jìn)行
* 團(tuán)隊(duì)成員都在dev上干活,每個(gè)人有自己的分支,時(shí)不時(shí)往`dev`上合并就可以了
BUG分支
- 用臨時(shí)分支來修復(fù)bug時(shí),可以將當(dāng)前分支未提交的內(nèi)容儲(chǔ)存到stash中,等bug修復(fù)完成后繼續(xù)操作
-
git stash
保存當(dāng)前工作進(jìn)度 -
git stash list
讀取保存的進(jìn)度列表 -
git stash apply
將保存的進(jìn)度恢復(fù)到工作區(qū)但是保留stash中的存檔 -
git stash drop
刪除保存的stash -
git stash pop
取出存檔,同時(shí)刪除stash -
git apply stash@{0}
恢復(fù)指定的stash
-
Feature分支
- 在添加一個(gè)新功能之前,為了防止實(shí)驗(yàn)代碼影響主分支內(nèi)容可以創(chuàng)建一個(gè)
feature
分支,在上面開發(fā)完成后合并 - 丟棄一個(gè)沒有被合并過的分支可以通過
git branch -D
強(qiáng)行刪除
多人協(xié)作
-
查看遠(yuǎn)程庫的信息
- git remote
- git remote -v查看更加詳細(xì)的信息
-
分支推送
- git push origin dev
-
master
分支時(shí)主分支,因此要隨時(shí)與遠(yuǎn)程庫同步 -
dev
時(shí)開發(fā)分支,所有成員在上面工作,所以也需要同步 - bug分支無需推送
- feature 是否推送取決于是否有多人協(xié)同開發(fā)
-
抓取分支
-
從遠(yuǎn)程庫克隆時(shí),只能看到遠(yuǎn)程庫的master分支,如果要在dev分支上開發(fā),就必須創(chuàng)建遠(yuǎn)程的dev分支到本地
$ git checkout -b dev origin/dev $ git pull <remote> <branch>
-
在
dev
上修改并時(shí)不時(shí)推送到遠(yuǎn)程$ git push origin dev
-
如果碰巧別人也
push
了對同樣文件的修改,則會(huì)發(fā)生沖突導(dǎo)致提交失敗,這是可以用git pull//如果提示no tracking information,說明本地分支尚未與遠(yuǎn)程分支建立連接 //指定本地dev分支與遠(yuǎn)程origin分支的鏈接 $ git branch --set-upstream dev origin/dev $ git pull //手動(dòng)解決沖突之后commit,push $ git commit $ git push origin dev
-
標(biāo)簽管理
創(chuàng)建標(biāo)簽
-
創(chuàng)建一個(gè)標(biāo)簽,總共分三步
- 切換到需要打標(biāo)簽的分支
git checkout <name>
- 打標(biāo)簽
git tag <tagname>
- 查看標(biāo)簽
git tag
git show <tagname>
查看標(biāo)簽信息 - 切換到需要打標(biāo)簽的分支
-
給一個(gè)只有id 的commit打標(biāo)簽
-
git log --pretty=oneline --abbrev-commit
找到歷史提交的commit id - 打標(biāo)簽
git tag <tagname> <commitid>
-
git tag -a <tagname> -m <message> <commitid>
創(chuàng)建帶有說明的標(biāo)簽,-a
指定標(biāo)簽名,-m
添加說明文字-s命令可以用PGP簽名標(biāo)簽
操作標(biāo)簽
- 刪除標(biāo)簽
git tag -d <tagname>
- 推送標(biāo)簽到遠(yuǎn)程
git push origin <tagname>
- 一次推送全部標(biāo)簽
git push origin --tags
- 刪除遠(yuǎn)程標(biāo)簽
- 先刪除本地標(biāo)簽
git tag -d <tagname>
- 然后從遠(yuǎn)程刪除
- 先刪除本地標(biāo)簽
自定義Git
忽略指定文件
- 在
.gitignore
文件中配置需要忽略的文件名,可以使用正則 - 把
.gitignore
文件提交到版本庫 - 檢驗(yàn)
.gitignore
是否生效的標(biāo)準(zhǔn)是git status
命令提示working directory clean
配置別名
使用
git config --global alias.<alias> <order>
為命令指定別名-
花哨的小技巧
//修改git log的字體樣式 git config --global alias.log "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
補(bǔ)充
Git clone
-
用法
git clone (-o 主機(jī)名) <url> <localdir>
-
git clone 支持多種協(xié)議
$ git clone http[s]://example.com/path/to/repo.git/ $ git clone ssh://example.com/path/to/repo.git/ $ git clone git://example.com/path/to/repo.git/ $ git clone /opt/git/project.git $ git clone file:///opt/git/project.git $ git clone ftp[s]://example.com/path/to/repo.git/ $ git clone rsync://example.com/path/to/repo.git/
remote補(bǔ)充
$ git remote show <主機(jī)名>
//查看主機(jī)信息
$ git remote add <主機(jī)名> <網(wǎng)址>
//添加主機(jī)
$ git remote rm <主機(jī)名>
//刪除主機(jī)
$ git remote rename <原主機(jī)名> <新主機(jī)名>
//遠(yuǎn)程主機(jī)改名
git fetch
-
git fetch
通常用于將遠(yuǎn)程主機(jī)的更新(commit)取回本地$ git fetch <遠(yuǎn)程主機(jī)名> //將遠(yuǎn)程主機(jī)上所有分支取回本地 $ git fetch <遠(yuǎn)程主機(jī)名> <分支名> //將指定分支取回本地
git fetch
取回的更新要用"遠(yuǎn)程主機(jī)名/分支名"的形式讀取git branch -r
查看遠(yuǎn)程分支git branch -a
查看所有分支-
取回遠(yuǎn)程分支后
//可以在遠(yuǎn)程分支的基礎(chǔ)上創(chuàng)建一個(gè)新的分支 $ git checkout -b newbranch //也可以在本地分支上合并遠(yuǎn)程分支 $ git merge origin/master $ git rebase origin/master
-
git pull/push
$ git pull <遠(yuǎn)程主機(jī)名> <遠(yuǎn)程分支>:<本地分支> $ git pull <遠(yuǎn)程主機(jī)名> <本地分支>:<遠(yuǎn)程分支> //手動(dòng)建立本地分支與遠(yuǎn)程分支的追蹤關(guān)系 $ git branch --set-upstream <本地分支> <遠(yuǎn)程主機(jī)/遠(yuǎn)程分支>
-
git push
的特殊用法//省略遠(yuǎn)程分支,默認(rèn)推送到與之有"追蹤關(guān)系"的遠(yuǎn)程分支 $ git push origin master //向遠(yuǎn)程推送空分支相當(dāng)于刪除origin主機(jī)上的對應(yīng)分支 $ git push origin :master #等同于 $ git push origin --delete master # 如果當(dāng)前分支與多個(gè)遠(yuǎn)程主機(jī)關(guān)聯(lián)可以使用`-u`指定默認(rèn)遠(yuǎn)程分支 $ git push -u origin master