最近要与部门同事一起做技术分享,我选择了Git,因为Git 是一种在全球范围都广受欢迎的版本控制系统。在开发过程中,为了跟踪代码,文档,项目等信息中的变化,版本控制变得前所未有的重要。
版本控制(Revision control)是一种在开发的过程中用于管理我们对文件、目录或工程等内容的修改历史,方便查看更改历史记录,备份以便恢复以前的版本的软件工程技术。
简单说就是用于管理多人协同开发项目的技术。
没有进行版本控制或者版本控制本身缺乏正确的流程管理,在软件开发过程中将会引入很多问题,如软件代码的一致性、软件内容的冗余、软件过程的事物性、软件开发过程中的并发性、软件源代码的安全性,以及软件的整合等问题。
1)、仓库(Repository)
受版本控制的所有文件修订历史的共享数据库
2)、工作空间(Workspace)
本地硬盘或Unix 用户帐户上编辑的文件副本
3)、工作树/区(Working tree)
工作区中包含了仓库的工作文件。您可以修改的内容和提交更改作为新的提交到仓库。
4)、暂存区(Staging area)
暂存区是工作区用来提交更改(commit)前可以暂存工作区的变化。
5)、索引(Index)
索引是暂存区的另一种术语。
6)、签入(Checkin)
将新版本复制回仓库
7)、签出(Checkout)
从仓库中将文件的最新修订版本复制到工作空间
8)、提交(Commit)
对各自文件的工作副本做了更改,并将这些更改提交到仓库
9)、冲突(Conflict)
多人对同一文件的工作副本进行更改,并将这些更改提交到仓库
10)、合并(Merge)
将某分支上的更改联接到此主干或同为主干的另一个分支
11)、分支(Branch)
从主线上分离开的副本,默认分支叫master
12)、锁(Lock)
获得修改文件的专有权限。
13)、头(HEAD)
头是一个象征性的参考,最常用以指向当前选择的分支。
14)、修订(Revision)
表示代码的一个版本状态。Git通过用SHA1 hash算法表示的ID来标识不同的版本。
15)、标记(Tags)
标记指的是某个分支某个特定时间点的状态。通过标记,可以很方便的切换到标记时的状态。
主流的版本控制器有如下这些:
版本控制产品非常的多(Perforce、Rational ClearCase、RCS(GNU Revision Control System)、Serena Dimention、SVK、BitKeeper、Monotone、Bazaar、Mercurial、SourceGear Vault),现在影响力最大且使用最广泛的是Git与SVN
记录文件每次的更新,可以对每个版本做一个快照,或是记录补丁文件,适合个人用,如RCS。
所有的版本数据都保存在服务器上,协同开发者从服务器上同步更新或上传自己的修改
所有的版本数据都存在服务器上,用户的本地只有自己以前所同步的版本,如果不连网的话,用户就看不到历史版本,也无法切换版本验证问题,或在不同分支工作。而且,所有数据都保存在单一的服务器上,有很大的风险这个服务器会损坏,这样就会丢失所有的数据,当然可以定期备份。代表产品:SVN、CVS、VSS
所有版本信息仓库全部同步到本地的每个用户,这样就可以在本地查看所有版本历史,可以离线在本地提交,只需在连网时push到相应的服务器或其他用户那里。由于每个用户那里保存的都是所有的版本数据,只要有一个用户的设备没有问题就可以恢复所有的数据,但这增加了本地存储空间的占用。
SVN是集中式版本控制系统,版本库是集中放在中央服务器的,而工作的时候,用的都是自己的电脑,所以首先要从中央服务器得到最新的版本,然后工作,完成工作后,需要把自己做完的活推送到中央服务器。集中式版本控制系统是必须联网才能工作,对网络带宽要求较高。
Git是分布式版本控制系统,没有中央服务器,每个人的电脑就是一个完整的版本库,工作的时候不需要联网了,因为版本都在自己电脑上。协同的方法是这样的:比如说自己在电脑上改了文件A,其他人也在电脑上改了文件A,这时,你们两之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。
Git是目前世界上最先进的分布式版本控制系统。
Git是免费、开源的
最初Git是为辅助 Linux 内核开发的,来替代 BitKeeper
作者:Linux和Git之父李纳斯·托沃兹(Linus Benedic Torvalds)1969、芬兰
优点:
缺点:
官网: https://git-scm.com/
源码: https://github.com/git/git/
打开 git官网,下载git对应操作系统的版本。
选择版本:
这里我选择下载64-bit Git for Windows Setup
选择安装配置信息
一直Next默认就好了,如果需要设置就要仔细读一下安装界面上的选项。
安装成功后在开始菜单中会有Git项,菜单下有3个程序:
Git Bash:Unix与Linux风格的命令行,使用最多,推荐最多
与DOS风格的命令有些区别,不习惯可以选择Git CMD
Git CMD:Windows风格的命令行
Git GUI:图形界面的Git,不建议初学者使用,尽量先熟悉常用命令
点击Create New Repository可以直接创建一个新的仓库。
Linux安装Git:sudo apt-get install git 命令行就可以安装了。
Mac OS安装Git: https://git-scm.com/download/mac,下载双击.pkg安装
1)、 cd : 改变目录。
2)、 cd . . 回退到上一个目录,直接cd进入默认目录
3)、 pwd : 显示当前所在的目录路径。
4)、 ls(ll): 都是列出当前目录中的所有文件,只不过ll(两个ll)列出的内容更为详细。
5)、 touch : 新建一个文件 如 touch index.js 就会在当前目录下新建一个index.js文件。
6)、 rm: 删除一个文件, rm index.js 就会把index.js文件删除。
7)、 mkdir: 新建一个目录,就是新建一个文件夹。
8)、 rm -r : 删除一个文件夹, rm -r src 删除src目录, 好像不能用通配符。
9)、 mv 移动文件, mv index.html src index.html 是我们要移动的文件, src 是目标文件夹,当然, 这样写,必须保证文件和目标文件夹在同一目录下。
10)、 reset 重新初始化终端/清屏。
11)、 clear 清屏。
12)、 history 查看命令历史。
13)、 help 帮助。
14)、 exit 退出。
15)、 #表示注释
使用git config -l 可以查看现在的git环境详细配置
查看不同级别的配置文件:
#查看系统config
git config --system --list
#查看当前用户(global)配置
git config --global --list
#查看当前仓库配置信息
git config --local --list
在Windows系统中,Git在$HOME目录中查找.gitconfig文件(一般位于C:\Documents and Settings\$USER下)
Git相关的配置文件有三个:
1)、 /etc/gitconfig:包含了适用于系统所有用户和所有项目的值。(Win:C:\Program Files\Git\mingw64\etc\gitconfig) –system 系统级
2)、~/.gitconfig:只适用于当前登录用户的配置。(Win:C:\Users\Administrator.gitconfig) –global 全局
3)、位于git项目目录中的.git/config:适用于特定git项目的配置。(Win:C:\gitProject) –local当前项目
注意:对于同一配置项,三个配置文件的优先级是1<2<3
这里可以直接编辑配置文件,通过命令设置后会响应到这里。
当你安装Git后首先要做的事情是设置你的用户名称和e-mail地址。这是非常重要的,因为每次Git提交都会使用该信息。它被永远的嵌入到了你的提交中:
$ git config --global user.name "zhangguo" #名称
$ git config --global user.email zhangguo@qq.com #邮箱
只需要做一次这个设置,如果你传递了–global 选项,因为Git将总是会使用该信息来处理你在系统中所做的一切操作。如果你希望在一个特定的项目中使用不同的名称或e-mail地址,你可以在该项目中运行该命令而不要–global选项。 总之–global为全局配置,不加为某个项目的特定配置。
1)、添加配置项
git config [--local|--global|--system] section.key value
[--local|--global|--system] #可选的,对应本地,全局,系统不同级别的设置,请看2.3.2
section.key #区域下的键
value #对应的值
–local 项目级
–global 当前用户级
–system 系统级
例如我们要在student区域下添加一个名称为height值为198的配置项,执行结果如下:
**2)、删除配置项 **
git config [--local|--global|--system] --unset section.key
将系统级的height配置项移除
git config --global color.ui true #打开所有的默认终端着色
git config --global alias.ci commit #别名 ci 是commit的别名
[alias]
co = checkout
ci = commit
st = status
pl = pull
ps = push
dt = difftool
l = log --stat
cp = cherry-pick
ca = commit -a
b = branch
user.name #用户名
user.email #邮箱
core.editor #文本编辑器
merge.tool #差异分析工具
core.paper "less -N" #配置显示方式
color.diff true #diff颜色配置
alias.co checkout #设置别名
git config user.name #获得用户名
git config core.filemode false #忽略修改权限的文件
所有config命令参数
语法: git config [<options>]
文件位置
--global #use global config file 使用全局配置文件
--system #use system config file 使用系统配置文件
--local #use repository config file 使用存储库配置文件
-f, --file <file> #use given config file 使用给定的配置文件
--blob <blob-id> #read config from given blob object 从给定的对象中读取配置
动作
--get #get value: name [value-regex] 获得值:[值]名[正则表达式]
--get-all #get all values: key [value-regex] 获得所有值:[值]名[正则表达式]
--get-regexp #get values for regexp: name-regex [value-regex] 得到的值根据正则
--get-urlmatch #get value specific for the URL: section[.var] URL 为URL获取特定的值
--replace-all #replace all matching variables: name value [value_regex] 替换所有匹配的变量:名称值[ value_regex ]
--add #add a new variable: name value 添加一个新变量:name值
--unset #remove a variable: name [value-regex] 删除一个变量名[值]:正则表达式
--unset-all #remove all matches: name [value-regex] 删除所有匹配的正则表达式:名称[值]
--rename-section #rename section: old-name new-name 重命名部分:旧名称 新名称
--remove-section #remove a section: name 删除部分:名称
-l, --list #list all 列出所有
-e, --edit #open an editor 打开一个编辑器
--get-color #find the color configured: slot [default] 找到配置的颜色:插槽[默认]
--get-colorbool #find the color setting: slot [stdout-is-tty] 发现颜色设置:槽[ stdout是TTY ]
类型
--bool #value is "true" or "false" 值是“真”或“假”。
--int #value is decimal number 值是十进制数。
--bool-or-int #value is --bool or --int 值--布尔或int
--path #value is a path (file or directory name) 值是路径(文件或目录名)
其它
-z, --null #terminate values with NUL byte 终止值与null字节
--name-only #show variable names only 只显示变量名
--includes #respect include directives on lookup 尊重包括查找指令
--show-origin #show origin of config (file, standard input, blob, command line) 显示配置(文件、标准输入、数据块、命令行)的来源
Git本地有三个工作区域:工作目录(Working Directory)、暂存区(Stage/Index)、资源库(Repository或Git Directory)。如果在加上远程的git仓库(Remote Directory)就可以分为四个工作区域。文件在这四个区域之间的转换关系如下:
日常使用只要记住下图6个命令:
创建本地仓库的方法有两种:一种是创建全新的仓库,另一种是克隆远程仓库。
需要用GIT管理的项目的根目录执行:
# 在当前目录新建一个Git代码库
$ git init
执行:
结果:
执行后可以看到,仅仅在项目目录多出了一个.git目录,关于版本等的所有信息都在这个目录里面。
当然如果使用如下命令,可以把创建目录与仓库一起完成:
# 新建一个目录,将其初始化为Git代码库
$ git init [project-name]
执行命令与运行结果:
另一种方式是克隆远程目录,由于是将远程服务器上的仓库完全镜像一份至本地,而不是取某一个特定版本,所以用clone而不是checkout,语法格式如下:
# 克隆一个项目和它的整个代码历史(版本信息)
$ git clone [url]
执行:
比如我们要从克隆的远程仓库托管在github上,地址为:https://github.com/zhangguo5/SuperPlus.git,这是一个公开的项目
结果:
版本控制就是对文件的版本控制,要对文件进行修改、提交等操作,首先要知道文件当前在什么状态,不然可能会提交了现在还不想提交的文件,或者要提交的文件没提交上。GIT不关心文件两个版本之间的具体差别,而是关心文件的整体是否有改变,若文件被改变,在添加提交时就生成文件新版本的快照,而判断文件整体是否改变的方法就是用SHA-1算法计算文件的校验和。
Unmodify: 文件已经入库, 未修改, 即版本库中的文件快照内容与文件夹中完全一致. 这种类型的文件有两种去处, 如果它被修改, 而变为Modified. 如果使用git rm移出版本库, 则成为Untracked文件
Modified: 文件已修改, 仅仅是修改, 并没有进行其他的操作. 这个文件也有两个去处, 通过git add可进入暂存staged状态, 使用git checkout 则丢弃修改过, 返回到unmodify状态, 这个git checkout即从库中取出文件, 覆盖当前修改
Staged: 暂存状态. 执行git commit则将修改同步到库中, 这时库中的文件和本地文件又变为一致, 文件为Unmodify状态. 执行git reset HEAD filename取消暂存, 文件状态为Modified
上面说文件有4种状态,通过如下命令可以查看到文件的状态:
#查看指定文件状态
git status [filename]
#查看所有文件状态
git status
命令:
结果:
foo.htm文件的状态为untracked(未跟踪),提示通过git add可以暂存
GIT在这一点做得很好,在输出每个文件状态的同时还说明了怎么操作,像上图就有怎么暂存、怎么跟踪文件、怎么取消暂存的说明。
工作区(Working Directory)就是你在电脑里能看到的目录。
版本库(Repository)工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
将untracked状态的文件添加到暂存区,语法格式如下:
# 添加指定文件到暂存区
$ git add [file1] [file2] ...
# 添加指定目录到暂存区,包括子目录
$ git add [dir]
# 添加当前目录的所有文件到暂存区
$ git add .
执行:
当执行如下命令时,会直接从暂存区删除文件,工作区则不做出改变
#直接从暂存区删除文件,工作区则不做出改变
git rm --cached <file>
执行命令
通过重写目录树移除add文件:
#如果已经用add 命令把文件加入stage了,就先需要从stage中撤销
git reset HEAD <file>...
当执行 “git reset HEAD” 命令时,暂存区的目录树会被重写,被 master 分支指向的目录树所替换,但是工作区不受影响。
示例:把f1.txt文件从暂存区撤回工作区
移除所有未跟踪文件
#移除所有未跟踪文件
#一般会加上参数-df,-d表示包含目录,-f表示强制清除。
git clean [options]
示例:
移除前:
执行移除:
移除后:
#只从stage中删除,保留物理文件
git rm --cached readme.txt
#不但从stage中删除,同时删除物理文件
git rm readme.txt
#把a.txt改名为b.txt
git mv a.txt b.txt
当执行提交操作(git commit)时,暂存区的目录树写到版本库(对象库)中,master 分支会做相应的更新。即 master 指向的目录树就是提交时暂存区的目录树。
当执行 “git reset HEAD” 命令时,暂存区的目录树会被重写,被 master 分支指向的目录树所替换,但是工作区不受影响。
当执行 “git rm –cached
当执行 “git checkout .” 或者 “git checkout —
当执行 “git checkout HEAD .” 或者 “git checkout HEAD
git diff用于显示WorkSpace中的文件和暂存区文件的差异
用”git status”只能查看对哪些文件做了改动,如果要看改动了什么,可以用:
#查看文件修改后的差异
git diff [files]
命令:
—a表示修改之前的文件,+++b表示修改后的文件
#比较暂存区的文件与之前已经提交过的文件
git diff --cached
也可以把WorkSpace中的状态和repo中的状态进行diff,命令如下:
#比较repo与工作空间中的文件差异
git diff HEAD~n
如果仓库中已经存在文件f4.txt,在工作区中对f4修改了,如果想撤销可以使用checkout,签出覆盖
检出命令git checkout是git最常用的命令之一,同时也是一个很危险的命令,因为这条命令会重写工作区
语法:
#用法一
git checkout [-q] [<commit>] [--] <paths>...
#用法二
git checkout [<branch>]
#用法三
git checkout [-m] [[-b]--orphan] <new_branch>] [<start_point>]
$ git checkout branch
#检出branch分支。要完成图中的三个步骤,更新HEAD以指向branch分支,以及用branch 指向的树更新暂存区和工作区。
$ git checkout
#汇总显示工作区、暂存区与HEAD的差异。
$ git checkout HEAD
#同上
$ git checkout -- filename
#用暂存区中filename文件来覆盖工作区中的filename文件。相当于取消自上次执行git add filename以来(如果执行过)的本地修改。
$ git checkout branch -- filename
#维持HEAD的指向不变。用branch所指向的提交中filename替换暂存区和工作区中相 应的文件。注意会将暂存区和工作区中的filename文件直接覆盖。
$ git checkout -- . 或写作 git checkout .
#注意git checkout 命令后的参数为一个点(“.”)。这条命令最危险!会取消所有本地的 #修改(相对于暂存区)。相当于用暂存区的所有文件直接覆盖本地文件,不给用户任何确认的机会!
$ git checkout commit_id -- file_name
#如果不加commit_id,那么git checkout -- file_name 表示恢复文件到本地版本库中最新的状态。
示例:
有些时候我们不想把某些文件纳入版本控制中,比如数据库文件,临时文件,设计文件等
在主目录下建立”.gitignore”文件,此文件有如下规则:
可以使用Linux通配符。例如:星号(*)代表任意多个字符,问号(?)代表一个字符,方括号([abc])代表可选字符范围,大括号({string1,string2,…})代表可选的字符串等。
如果名称的最前面有一个感叹号(!),表示例外规则,将不被忽略。
如果名称的最前面是一个路径分隔符(/),表示要忽略的文件在此目录下,而子目录中的文件不忽略。
如果名称的最后面是一个路径分隔符(/),表示要忽略的是此目录下该名称的子目录,而非文件(默认文件或目录都忽略)。
如:
#为注释
*.txt #忽略所有 .txt结尾的文件
!lib.txt #但lib.txt除外
/temp #仅忽略项目根目录下的TODO文件,不包括其它目录temp
build/ #忽略build/目录下的所有文件
doc/*.txt #会忽略 doc/notes.txt 但不包括 doc/server/arch.txt
更多规则: http://www.cnblogs.com/kevingrace/p/5690241.html
示例:
创建一个.gitignore文件忽视所有的日志文件
查看状态:
从上图中可以看出2个日志文件并没有添加到暂存区,直接被忽视了。
针对各种语言与项目的Git忽视文件:
https://github.com/kaedei/gitignore https://github.com/github/gitignore
通用的java忽视文件:
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
通用的Visual Studio开发项目忽视文件:
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Typescript v1 declaration files
typings/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
通过add只是将文件或目录添加到了index暂存区,使用commit可以实现将暂存区的文件提交到本地仓库。
# 提交暂存区到仓库区
$ git commit -m [message]
# 提交暂存区的指定文件到仓库区
$ git commit [file1] [file2] ... -m [message]
# 提交工作区自上次commit之后的变化,直接到仓库区,跳过了add,对新文件无效
$ git commit -a
# 提交时显示所有diff信息
$ git commit -v
# 使用一次新的commit,替代上一次提交
# 如果代码没有任何新变化,则用来改写上一次commit的提交信息
$ git commit --amend -m [message]
# 重做上一次commit,并包括指定文件的新变化
$ git commit --amend [file1] [file2] ...
示例:
提交前的状态
提交:
提交后的状态:
从上图中可以看出暂存区中没有了bar.htm
修订提交
如果我们提交过后发现有个文件改错了,或者只是想修改提交说明,这时可以对相应文件做出修改,将修改过的文件通过”git add”添加到暂存区,然后执行以下命令:
#修订提交
git commit --amend
撤销提交(commit)
原理就是放弃工作区和index的改动,同时HEAD指针指向前一个commit对象
#撤销上一次的提交
git reset --hard HEAD~1
要通过git log查看提交日志,也可直接指定提交编号或序号
示例:
撤销提交
git revert <commit-id>
这条命令会把指定的提交的所有修改回滚,并同时生成一个新的提交。
查看提交日志可以使用git log指令,语法格式如下:
#查看提交日志
git log [<options>] [<revision range>] [[\--] <path>…]
示例:
“git log –graph”以图形化的方式显示提交历史的关系,这就可以方便地查看提交历史的分支信息,当然是控制台用字符画出来的图形。
“git log -1″则表示显示1行。
使用history可以查看您在bash下输入过的指令:
几乎所有输入过的都被记录下来的,不愧是做版本控制的。
查看所有分支日志
“git reflog”中会记录这个仓库中所有的分支的所有更新记录,包括已经撤销的更新。
使用git ls-files指令可以查看指定状态的文件列表,格式如下:
#查看指定状态的文件
git ls-files [-z] [-t] [-v] (--[cached|deleted|others|ignored|stage|unmerged|killed|modified])* (-[c|d|o|i|s|u|k|m])*
示例:
1)、撤销暂存区更新
使用”git add”把更新提交到了暂存区。这时”git status”的输出中提示我们可以通过”git reset HEAD
示例:f6已经提交,工作区修改,暂存区修改,撤销
2)、撤销本地仓库更新
使用git log查看提交日志
撤销提交有两种方式:使用HEAD指针和使用commit id
在Git中,有一个HEAD指针指向当前分支中最新的提交。当前版本,我们使用”HEAD^”,那么再钱一个版本可以使用”HEAD^^”,如果想回退到更早的提交,可以使用”HEAD~n”。(也就是,HEAD^=HEAD~1,HEAD^^=HEAD~2)
git reset --hard HEAD^
git reset --hard HEAD~1
git reset --59cf9334cf957535cb328f22a1579b84db0911e5
示例:回退到添加f6
回退前:
回退后:
现在又想恢复被撤销的提交可用”git reflog”查看仓库中所有的分支的所有更新记录,包括已经撤销的更新,撤销方法与前面一样。
git reset --hard HEAD@{7}
git reset --hard e0e79d7
–hard:撤销并删除相应的更新
–soft:撤销相应的更新,把这些更新的内容放到Stage中
1)、删除未跟踪文件
如果文件还是未跟踪状态,直接删除文件就可了,bash中使用rm可以删除文件,示例如下:
2)、删除已提交文件
-f 强制删除,物理删除了,同时删除工作区和暂存区中的文件
撤销删除:
#to discard changes in working directory
git checkout -- <file>...
3)、删除暂存区的文件,不删除工作区的文件
使用git reset HEAD
Git很强大,很灵活,这是毋庸置疑的。但也正因为它的强大造成了它的复杂,因此会有很多奇奇怪怪的问题出现,多用就好了。
分支在GIT中相对较难
分支就是科幻电影里面的平行宇宙,当你正在电脑前努力学习Git的时候,另一个你正在另一个平行宇宙里努力学习SVN。
如果两个平行宇宙互不干扰,那对现在的你也没啥影响。不过,在某个时间点,两个平行宇宙合并了,结果,你既学会了Git又学会了SVN!
分支在实际中有什么用呢?假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。
现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。
Git分支的速度非常快。
截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支。HEAD严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是当前分支。
git分支中常用指令:
# 列出所有本地分支
$ git branch
# 列出所有远程分支
$ git branch -r
# 列出所有本地分支和远程分支
$ git branch -a
# 新建一个分支,但依然停留在当前分支
$ git branch [branch-name]
# 新建一个分支,并切换到该分支
$ git checkout -b [branch]
# 新建一个分支,指向指定commit
$ git branch [branch] [commit]
# 新建一个分支,与指定的远程分支建立追踪关系
$ git branch --track [branch] [remote-branch]
# 切换到指定分支,并更新工作区
$ git checkout [branch-name]
# 切换到上一个分支
$ git checkout -
# 建立追踪关系,在现有分支与指定的远程分支之间
$ git branch --set-upstream [branch] [remote-branch]
# 合并指定分支到当前分支
$ git merge [branch]
# 选择一个commit,合并进当前分支
$ git cherry-pick [commit]
# 删除分支
$ git branch -d [branch-name]
# 删除远程分支
$ git push origin --delete [branch-name]
$ git branch -dr [remote/branch]
默认分支是这样的,master是主分支
1)、新建一个分支,但依然停留在当前分支,使用:$ git branch [branch-name]
切换分支到dev1后的结果:
关于分支廖雪峰解释的比较清楚,我们引用一下。
当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:
你看,Git创建一个分支很快,因为除了增加一个dev指针,改改HEAD的指向,工作区的文件都没有任何变化!
不过,从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变:
假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并:
所以Git合并分支也很快!就改改指针,工作区内容也不变!
合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支:
2)、切换分支,git branch
切换为上一个分支
3)、新建一个分支,并切换到该分支,$ git checkout -b [branch]
4)、新建一个分支,指向指定commit使用命令:$ git branch [branch] [commit]
上面创建了dev3分支且指向了master中首次提交的位置,切换到dev3查看日志如下:
master上本来有两个提交记录的,此时的dev3指向的是第1次提交的位置
5)、新建一个分支,与指定的远程分支建立追踪关系使用命令:$ git branch –track [branch] [remote-branch]
1)、列出所有本地分支使用$ git branch
2)、列表所有远程分支使用$ git branch -r
3)、列出所有本地分支和远程分支使用$ git branch -a
合并指定分支到当前分支使用指令$ git merge [branch]
这里的合并分支就是对分支的指针操作,我们先创建一个分支再合并到主分支:
这里的file11.txt主分支与dev6的内容现在是不同的,因为在dev6中已被修改过,我们可以使用指令查看:
现在我们将dev6合并到主分支中去,从下图中可以看出dev6中有一次提交,而master并没有
合并后在master上查看file11.txt文件内容与dev6上的内容就一样了,合并后dev6中多出的提交在master也拥有了。
如果同一个文件在合并分支时都被修改了则会引起冲突,如下所示:
提交前两个分支的状态
在dev6分支中同样修改file11.txt
dev6与master分支中file11.txt文件都被修改且提交了,现在合并分支
提示冲突,现在我们看看file11.txt在master分支中的状态
Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,其中<<<HEAD是指主分支修改的内容,>>>>>dev6 是指dev6上修改的内容
解决的办法是我们可以修改冲突文件后重新提交,请注意当前的状态产master | MERGING:
重新提交后冲突解决:
手动解决完冲突后就可以把此文件添 加到索引(index)中去,用git commit命令来提交,就像平时修改了一个文件 一样。
用git log –graph命令可以看到分支合并图。
**分支策略*
master主分支应该非常稳定,用来发布新版本,一般情况下不允许在上面工作,工作一般情况下在新建的dev分支上工作,工作完后,比如上要发布,或者说dev分支代码稳定后可以合并到主分支master上来。
删除本地分支可以使用命令:$ git branch -d [branch-name],-D(大写)强制删除
删除远程分支可以使用如下指令:
$ git push origin --delete [branch-name]
$ git branch -dr [remote/branch]
-d表示删除分支。分支必须完全合并在其上游分支,或者在HEAD上没有设置上游
-r表示远程的意思remotes,如果-dr则表示删除远程分支
通过命令行可以深刻的理解Git,Git GUI或IDE插件却可以更加直观操作Git,常用的Git GUI有如下这些:
全球开发人员交友俱乐部提供的强大工具,功能完善,使用方便。对于使用GitHub的开发人员来说是非常便捷的工具。
GitHub for Desktop不带三方合并工具,你必须自己手动解决冲突才可以。
– 免费
– 同时支持 Windows 和 Mac:对于需要经常在不同的操作系统间切换的开发人员来说非常方便。
– 漂亮的界面:作为每天盯着看的工具,颜值是非常重要的
– 支持Pull Request:直接从客户端提交PR,很方便
– Timeline 支持:直接在时间线上显示每次提交的时间点和大小
– 支持git LFS:存储大文件更加节省空间和高效
– 不支持三方合并:需要借助第三方工具才行
SourceTree是老牌的Git GUI管理工具了,也号称是最好用的Git GUI工具。强大,功能丰富,基本操作和高级操作都设计得非常流畅,适合初学者上手,支持Git Flow。
– 免费
– 功能强大:无论你是新手还是重度用户,SourceTree 都会让你觉得很顺手。对于非常重度用户,Source Tree还支持自定义脚本的执行。
– 同时支持 Windows 和 Mac 操作系统
– 同时支持 Git 和 Mercurial 两种 VCS
– 内置GitHub, BitBucket 和 Stash 的支持:直接绑定帐号即可操作远程repo
小乌龟,SVN的超广泛使用也使得这个超好用的Svn客户端成了几乎每个开发人员的桌面必备软件。小乌龟只提供Windows版本,提供中文版支持的。
– 免费
– 只支持Windows操作系统:与文件管理器的良好集成
– 中文界面
– 与TortoiseSVN一脉相承的操作体验
安装Git时会集成安装Gui工具,在Git菜单下可以找到,特点是:免费、简单、不需要额外安装
对于使用IDE进行开发的程序员来说,可以不离开常用的IDE就直接操作源代码管理系统是最好的选择,以下是我对几个常见的IDE集成的git客户端:
作为Java集成开发环境的代表,Eclipse内置了egit这个插件来提供git的集成支持。实话实说,这个插件的功能非常丰富,无论是普通的clone, commit, pull/push操作;还是复杂一些的git flow都有支持。
VS里面的Git支持已经相当的完善。直接克隆github上的repo
1)、帮助文档
完整的安装了Git后有一个官方帮助,这是最权威的资料,方法如下:
比如我们要查看git commit的使用
执行时会打开对应的git帮助文档,其实就在本地,当然您也可以去官网在线搜索,地址是:https://git-scm.com/docs。
2)、信息查看与统计命令
#统计某人的代码提交量,包括增加,删除:
git log --author="$(git config --get user.name)" --pretty=tformat: --numstat | gawk '{ add += $1 ; subs += $2 ; loc += $1 - $2 } END { printf
"added lines: %s removed lines : %s total lines: %s\n",add,subs,loc }' -
#仓库提交者排名前 5(如果看全部,去掉 head 管道即可):
git log --pretty='%aN' | sort | uniq -c | sort -k1 -n -r | head -n 5
#仓库提交者(邮箱)排名前 5:这个统计可能不会太准,因为很多人有不同的邮箱,但会使用相同的名字
git log --pretty=format:%ae | gawk -- '{ ++c[$0]; } END { for(cc in c) printf "%5d %s\n",c[cc],cc; }' | sort -u -n -r | head -n 5
#贡献者统计:
git log --pretty='%aN' | sort -u | wc -l
#提交数统计:
git log --oneline | wc -l
# 显示有变更的文件
$ git status
# 显示当前分支的版本历史
$ git log
# 显示commit历史,以及每次commit发生变更的文件
$ git log --stat
# 搜索提交历史,根据关键词
$ git log -S [keyword]
# 显示某个commit之后的所有变动,每个commit占据一行
$ git log [tag] HEAD --pretty=format:%s
# 显示某个commit之后的所有变动,其"提交说明"必须符合搜索条件
$ git log [tag] HEAD --grep feature
# 显示某个文件的版本历史,包括文件改名
$ git log --follow [file]
$ git whatchanged [file]
# 显示指定文件相关的每一次diff
$ git log -p [file]
# 显示过去5次提交
$ git log -5 --pretty --oneline
# 显示所有提交过的用户,按提交次数排序
$ git shortlog -sn
# 显示指定文件是什么人在什么时间修改过
$ git blame [file]
# 显示暂存区和工作区的差异
$ git diff
# 显示暂存区和上一个commit的差异
$ git diff --cached [file]
# 显示工作区与当前分支最新commit之间的差异
$ git diff HEAD
# 显示两次提交之间的差异
$ git diff [first-branch]...[second-branch]
# 显示今天你写了多少行代码
$ git diff --sho