Git
Git是一个分布式版本控制工具,用来管理多人写作的代码。同时也是一个内容管理系统。
Git与SVN的区别:
- Git是分布式的,svn不是。这是最核心的区别
- Git把内容按元数据方式存储,而SVN是按文件:所有的资源控制系统都是把文件的原信息隐藏在一个类似.svn .cvs等的文件夹里
- Git分支和SVN分支的不同:分支在SVN中一点都不特别,其实他就是版本库中的另外一个目录
- Git没有一个全局的版本号,而SVN有
- Git的内容完整性要优于SVN:Git的内容存储使用的是SHA-1哈希算法,这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏
1、Git安装
Windows平台上的安装,到官网https://gitforwindows.org/,下载安装包,一路确认,完成安装。
安装完成后,右键git bash here,可以使用命令行的git工具(自带SSH客户端)。
Git配置
Git提供了一个叫做git config的工具,专门用来配置或读取相应的工作变量。
这些环境变量,决定了Git在各个环节的具体工作方式和行为。这些变量可以存放在三个不同的地方:
- /etc/gitconfig 文件:系统中对所有用户都普遍使用的配置。若使用
git config --system
选项,读写的就是这个文件D:\smy_software\git\Git\etc\gitconfig
。 - ~/.gitconfig:用户目录下的配置文件只适用于该永固。若使用
git config --global
选项,读写的就是这个文件。C:\Users\10170\.gitconfig
- 当前项目的Git目录中的配置文件(也就是工作目录中的
/.git/config
文件):这里的配置仅仅针对当前项目有效。每一个级别的配置都会覆盖上层的相同配置,所以.git/config里的配置会覆盖/etc/gitconfig中的同名变量。
项目路径/.git/config
文件配置如下:
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
[remote "origin"]
url = http://项目地址.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
因为我使用过git config --global 命令配置过用户信息,所以这里使用的是2中的用户信息,这个文件里只记录了仓库的配置信息。
用户目录/.gitconfig配置信息
[user]
email = 邮箱
name = 用户名
[core]
autocrlf = false
在 Windows 系统上,Git 会找寻用户主目录下的 .gitconfig 文件。主目录即 $HOME 变量指定的目录,一般都是 C:\Documents and Settings$USER。
此外,Git 还会尝试找寻 /etc/gitconfig 文件,只不过看当初 Git 装在什么目录,就以此作为根目录来定位。
配置用户信息
# 配置个人的用户名称和电子邮件地址
git config --global user.name "xxx"
git config --global user.email [email protected]
如果使用了 --global选项,那么更改的配置文件就是位于用户主目录下的./gitconfig
文件,以后所有的项目都会默认使用这里配置的用户信息。
如果要在某个特定的项目中使用其他名字或者电邮,只要去掉--global
选项重新配置即可,新的设定保存在当前项目的 .git/config
文件里。
适用于工作项目和个人项目分开的场景。例如,在xxx/A目录我使用github账号远程我的github仓库,在xxx/B目录使用gitLab账号远程公司的gitLab仓库。
差异分析工具
经常用在解决合并冲突时使用差异分析工具。可以使用如下命令配置
# 改用vimdiff
git config --global merge.tool vimdiff
Git 可以理解 kdiff3,tkdiff,meld,xxdiff,emerge,vimdiff,gvimdiff,ecmerge,和 opendiff 等合并工具的输出信息。
查看配置信息
检查已有的配置信息,可以使用如下命令
git config --list
注意:在idea中的终端中运行这个命令输出的信息是不完全的,需要在git bash中运行这个才可以看到完整的配置信息。
2、Git工作流程
一般工作流程如下:
- 克隆 Git 资源作为工作目录。
- 在克隆的资源上添加或修改文件。
- 如果其他人修改了,你可以更新资源。
- 在提交前查看修改。
- 提交修改。
- 在修改完成后,如果发现错误,可以撤回提交并再次修改并提交。
如图所示
3、Git原理
基本概念
我们先来理解下 Git 工作区、暂存区和版本库概念:
- 工作区:就是你在电脑里能看到的目录。
- 暂存区:英文叫 stage 或 index。一般存放在 .git 目录下的 index 文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。
- 版本库:工作区有一个隐藏目录 .git,这个不算工作区,而是 Git 的版本库。
- 图中左侧为工作区,右侧为版本库。在版本库中标记为 "index" 的区域是暂存区(stage/index),标记为 "master" 的是 master 分支所代表的目录树。
- 图中我们可以看出此时 "HEAD" 实际是指向 master 分支的一个"游标"。所以图示的命令中出现 HEAD 的地方可以用 master 来替换。
- 图中的 objects 标识的区域为 Git 的对象库,实际位于 ".git/objects" 目录下,里面包含了创建的各种对象及内容。
- 当对工作区修改(或新增)的文件执行 git add 命令时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,而该对象的ID被记录在暂存区的文件索引中。
- 当执行提交操作(git commit)时,暂存区的目录树写到版本库(对象库)中,master 分支会做相应的更新。即 master 指向的目录树就是提交时暂存区的目录树。
- 当执行 git reset HEAD 命令时,暂存区的目录树会被重写,被 master 分支指向的目录树所替换,但是工作区不受影响。
- 当执行 git rm --cached
命令时,会直接从暂存区删除文件,工作区则不做出改变。 - 当执行 git checkout . 或者 git checkout --
命令时,会用暂存区全部或指定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区中的改动。 - 当执行 git checkout HEAD . 或者 git checkout HEAD
命令时,会用 HEAD 指向的 master 分支中的全部或者部分文件替换暂存区和以及工作区中的文件。这个命令也是极具危险性的,因为不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改动。
4、Git基本操作
Git的工作就是创建和保存用户项目的快照及与之后的快照进行对比。
说明:
- workspace:工作区
- staging area:暂存区/缓存区
- local repository:版本库或本地仓库
- remote repository:远程仓库
创建仓库命令
命令 | 说明 |
---|---|
git init |
初始化仓库。 |
git clone |
拷贝一份远程仓库,也就是下载一个项目。 |
一个文件夹成为一个git仓库的标志是,这个文件夹下有一个.git的隐藏文件夹。这个就是版本库,里面还有暂存区。这个文件夹下的其他文件作为被git管理的文件。
提交与修改
Git 的工作就是创建和保存你的项目的快照及与之后的快照进行对比。
下表列出了有关创建与提交你的项目的快照的命令:
命令 | 说明 |
---|---|
git add |
添加文件到暂存区 |
git status |
查看仓库当前的状态,显示有变更的文件。 |
git diff |
比较文件的不同,即暂存区和工作区的差异。 |
git commit |
提交暂存区到本地仓库。 |
git reset |
回退版本。 |
git rm |
将文件从暂存区和工作区中删除。 |
git mv |
移动或重命名工作区文件。 |
提交日志
命令 | 说明 |
---|---|
git log |
查看历史提交记录 |
git blame <file> |
以列表形式查看指定文件的历史修改记录 |
远程操作
命令 | 说明 |
---|---|
git remote |
远程仓库操作 |
git fetch |
从远程获取代码库 |
git pull |
下载远程代码并合并 |
git push |
上传远程代码并合并 |
5、Git分支管理
Git分支实际上是指向更改快照的指针。
当切换到一个分支的时候,Git会用此分支最后一次提交(commit)的快照替换掉工作区的内容。所以多个分支不需要多个目录。
命令 | 说明 |
---|---|
git branch |
查看所有的分支,并且高亮显示当前所在分支 |
git branch branchname |
创建新分支,不切换到新分支。此时新分支指向工作区中的文件 |
git checkout branchname |
切换到branchname分支。 |
git checkout -b branchname |
创建并切换到branchname分支,相当于前两条命令的组合。此时新分支指向工作区中的文件 |
git merge source |
合并分支,将source分支合并到当前所在的分支。在git bash中默认不会删除原分支;在GitLab中默认勾选了Delete Source branch,会自动删除合并的source分支。 |
git branch -d dev |
删除dev分支,注意当前所在分支不能为dev分支,会报错。必须切换到其他分支再执行这个命令 |
git status |
可以用来查看那些因包含合并冲突而处于未合并(unmerged)状态的文件 |
git diff |
显示合并冲突的地方 |
git merge的三种情况
- 快进(无冲突)
- 描述:dev从master分支上创建,dev分支commit了多次后,并且master分支没有执行commit操作。
- 此时,没有发生冲突,可以进行自动merge
- 不会自动commit
- 非快进,修改不同文件(无冲突)
- 描述:dev从master分支上创建,dev分支commit了多次后,master分支也提交了多次。并且两个分支修改的不是一个文件。
- 此时,没有发生冲突,可以进行自动merge
- 合并后的版本,会自动commit一次
- 非快进,修改相同文件(有冲突)
- 描述:dev从master分支上创建,dev分支commit了多次后,master分支也提交了多次。并且两个分支修改的是一个文件。
- 此时,会发生冲突,自动合并失败,需要手动解决冲突。
- 使用命令
git status
可以查看是哪些文件发生了冲突 - 使用命令
git diff
可以查看哪些文件的哪个地方发生冲突。 - 手动打开这些文件,修改文件内容。vim
- 手动提交
git add .
git commit -m "xxx"
6、Git查看提交历史
Git 提交历史一般常用两个命令:
- git log - 查看历史提交记录。
- git blame <file> - 以列表形式查看指定文件的历史修改记录。
命令 | 说明 |
---|---|
git log |
查看提交记录,第一条是最新的 |
git log --oneline |
查看历史记录的简洁版本 |
git log --graph |
查看历史中什么时候出现了分支、合并。 |
git log --reverse --oneline |
逆向显示所有日志 |
git log --author |
查看指定用户提交的部分,如git log --author=Linus --oneline -5 |
7、Git标签
命令 | 说明 |
---|---|
git tag -a v1.0 |
为最新一次的commit打上标签,-a表示创建一个带注解的标签。不用-a也可以创建标签,但是它不会记录标签是什么时候打的,谁打的,也不会添加标签的注解。 |
git tag |
查看所有的标签 |
git tag -a v0.9 85fc7e7 |
为某个commit追加标签。与上面的区别是一个是为最新的commit打标签,这个是为指定的(可以不是最新的)commit打标签。 |
8、使用远程仓库
通过第三方的(github)或者自建的服务器,实现与其他人共同开发,版本控制。
命令 | 说明 |
---|---|
git remote add [shortname] [url] |
添加一个新的远程库,shortname一般为origin,url是远程仓库的地址。连接完成之后,可以将本地的commit push到远程仓库中。 |
git remote |
查看当前配置有哪些远程仓库 |
git remote -v |
查看当前配置有哪些远程仓库,显示url和方式 |
git fetch |
从远程仓库下载最新分支与数据。该命令执行完后需要手动执行 git merge 远程分支到你所在的分支。 |
git pull <远程主机名> <远程分支名>:<本地分支名> |
相当于git fetch 和 git merge的组合 |
git push origin <source>:<destination> |
推送当前分支到远程分支 |
git remote rm [别名] |
删除远程仓库 |