Git入门
1. Git结构
1.1 Git的目录结构
工作区、暂存区、本地库
工作区就是日常编写代码的地方,一个项目目录叫做一个工作区
暂存区是我们文件修改的临时存储区
本地库就是文件历史版本存放的地方(.git目录)
1.2 Git管理下的文件
git库所在的文件夹中的文件大致有4种状态
- Untracked: 未跟踪, 此文件在文件夹中, 但并没有加入到git库, 不参与版本控制. 通过
git add
状态变为Staged
. - Unmodify: 文件已经入库, 未修改, 即版本库中的文件快照内容与文件夹中完全一致. 这种类型的文件有两种去处, 如果它被修改, 而变为
Modified
. 如果使用git rm
移出版本库, 则成为Untracked
文件 - Modified: 文件已修改, 仅仅是修改, 并没有进行其他的操作. 这个文件也有两个去处, 通过
git add
可进入暂存staged
状态, 使用git checkout
则丢弃修改过, 返回到unmodify
状态, 这个git checkout
即从库中取出文件, 覆盖当前修改 - Staged: 暂存状态. 执行
git commit
则将修改同步到库中, 这时库中的文件和本地文件又变为一致, 文件为Unmodify
状态. 执行git reset HEAD filename
取消暂存, 文件状态为Modified
。
2. Git命令操作
2.1 本地仓库初始化
-
命令:git init
-
作用:将项目目录设置为git仓库。在该目录下对所有文件的操作都可以被git进行管理。
-
注意:该命令会在项目目录中生成一个本地库目录.git,该目录存放本地库相关的子目录和文件,不要对其进行胡乱的操作。
2.2 设置签名
-
格式:用户名+email,如username=tang,email=tang@email.com
注意:这里的签名和登录远程仓库的账号和密码没有任何关系。
-
作用:区分不同开发人员的身份
-
类别:
-
项目级别/仓库级别:仅在当前仓库目录范围内有效,签名保存在.git/config文件中
git config user.name tang
git config user.email tang@email.com
-
-
系统级别:登录当前操作系统的用户,在整个操作系统中有效,签名文件存放在系统用户的.gitconfig文件中
git config --global user.name tang_g
git config --global user.email tang_g@email.com
-
级别的优先级:
就近原则:项目级别优先于系统用户级别,二者都有时采用项目级别的签名。
如果只有系统级别的用户,就以系统级别的用户为准。二者都没有是不允许的。
2.3 基本操作
2.3.1 添加
git add
将工作区中新建或修改的文件交给git管理,即将工作区中的文件添加到缓存区中
2.3.2 提交
git commit -m "msg"
将缓存区中的文件提交到本地仓库进行储存
2.3.3 查看状态
git status
查看当前工作区和暂存区中的状态
红色表示没有add,绿色表示没有commit
- 工作区中有新建的文件未被追踪,即有新建的文件未被git管理,没有将文件添加到缓存区
- 缓存区中有新文件但并未将其提交到本地库,可以用git rm --cached (filename) 命令取消对文件的追踪
-
文件已提交
-
文件修改后,可用git add 添加修改到缓存区或者git restore (filename) 撤销对文件的修改
2.3.4 查看历史记录
查看历史记录的方式
git log
显示详细信息
git log --pretty=oneline
显示简略信息
git log --oneline
检索比较简短,只显示当前指针所在版本之前的版本,当指针往回退时,以指针所在版本为最新,比指针所在版本更加新的版本不显示
git reflog
增加显示版本回退步数,HEAD@{移到该版本需要的步数}
2.3.5 版本的前进后退
版本的前进后退实质上就是操作指针进行工作,通过移动指针指向的版本来将文件恢复到之前操作的版本。
基于索引值(推荐)
git reset --hard [局部索引值]
使用^符号
git reset --hard HEAD^
使用该方法只能后退版本,不能前进。一个 ^ 符号表示一个版本,n个 ^ 符号表示n个版本。
使用 ~ 符号
git reset --hard HEAD~n
该方法同样也只能后退,不能前进,但不用写很多的符号,只要写数字,n代表要后退的n个版本。
reset 三个参数的对比
最新状态
- soft参数
- 仅仅在本地库中移动HEAD指针,没有对工作区中的文件进行修改
相当与在工作区中对文件进行了修改,插入了hhh,然后将文件git add 提交到了暂存区,工作区与缓存区同步到新的版本2,而未提交到本地库,本地库没有同步。而实际上只是本地库指针回退一步
- mixed参数
- 在本地库中移动HEAD指针
- 重置暂存区,不会对工作区文件进行修改
相当于在工作区中对文件进行修改,插入了hhh,没有提交到暂存区。而实际上只是本地库和缓存区都回退了一步
- hard参数
- 在本地库中移动HEAD指针
- 重置暂存区
- 重置工作区,对文件进行修改
三个区域同时回退,不存在异步,版本一致。相当于已经进行了git add和git commit操作
找回删除文件
前提:删除前,文件存在的状态提交到了本地库中。
操作:git reset --hard [指针位置]
- 删除操作未提交到本地库:指针位置使用HEAD。
- 删除操作已提交到本地库:指针位置指向为删除的历史版本。
2.3.6 比较文件
当不指定文件名时比较多个文件
- 将工作区的文件和缓存区的文件比较
git diff [文件名]
- 将工作区的文件和本地库的历史版本比较
git diff [本地库中历史版本] [文件名]
3. Git 分支
3.1 分支简介
3.1.1 文件提交保存
在理解Git的分支前,先弄清楚Git是如何保存数据的。假设仓库中有三个文件对象README、test.rb、LICENSE。
- git add 添加的时候会用SHA-1 哈希算法对文件计算校验和,然后把当前版本的文件快照保存到 Git 仓库中(Git 使用 blob 对象来保存它们),将校验和加入到暂存区域等待提交。
- git commit 提交的时候Git会先计算每一个子目录(本例中只有项目根目录)的校验和,然后在 Git 仓库中这些校验和保存为树对象。 随后,Git 便会创建一个提交对象,它除了包含上面提到的那些信息外,还包含指向这个树对象(项目根目录)的指针。如此一来,Git 就可以在需要的时候重现此次保存的快照。
现在,Git 仓库中有五个对象:三个 blob 对象(保存着文件快照)、一个树对象(记录着目录结构和 blob 对象索引)以及一个提交对象(包含着指向前述树对象的指针和所有提交信息)。
多次修改提交后的对象及其树结构:
3.2 分支创建和切换
3.2.1 分支的创建
git branch testing
Git 的分支,本质上仅仅是指向提交对象的可变分支。Git 的默认分支名字是 master
。 Git创建分支实际上是为你创建了一个可移动的指针。
3.2.2 分支的切换
git checkout testing
切换到testing分支上,对文件进行操作,并将其提交到了本地仓库中。此时,testing分支会比master分支前进一个版本
注意:分支切换会改变你工作目录中的文件
3.3 分支的合并
3.3.1 合并操作
git merge [分支名]
现有这么一个分支
将iss3分支合并到master分支中。此时你的开发历史从一个更早的地方开始分叉开来(diverged)。 因为,master
分支所在提交并不是 iss53
分支所在提交的直接祖先,Git 不得不做一些额外的工作。 出现这种情况的时候,Git 会使用两个分支的末端所指的快照(C4
和 C5
)以及这两个分支的工作祖先(C2
),做一个简单的三方合并。
Git 将此次三方合并的结果做了一个新的快照并且自动创建一个新的提交指向它。 这个被称作一次合并提交,它的特别之处在于他有不止一个父提交。
此时的C6版本实际上是由C2、C4、C5三个版本合并而来的。
3.3.2 冲突分支合并
有时候合并操作不会如此顺利。 如果你在两个不同的分支中,对同一个文件的同一个部分进行了不同的修改,Git 就没法干净的合并它们。在合并它们的时候就会产生合并冲突:
$ git merge iss53
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
出现冲突的文件会包含一些特殊区段,看起来像下面这个样子:
<<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
please contact us at support@github.com
</div>
>>>>>>> iss53:index.html
这表示 HEAD
所指示的版本(也就是你的 master
分支所在的位置,因为你在运行 merge 命令的时候已经检出到了这个分支)在这个区段的上半部分(=======
的上半部分),而 iss53
分支所指示的版本在 =======
的下半部分。
在解决了冲突之后,并且 <<<<<<<
, =======
, 和 >>>>>>>
这些行被完全删除了,可以用git add来标记冲突已被解决,然后使用git commit 提交来完成合并。
4. 远程仓库
4.1 创建远程仓库地址别名
- 查看当前所有远程地址别名
git remote -v
- 创建远程仓库地址
git remote add [别名] [远程地址]
4.2 推送
git push [别名] [分支名]
4.3 克隆
git clone [远程地址]
效果:
- 完整的仓库克隆到本地
- 创建orgin的远程别名
- 初始化本地仓库
4.4 邀请加入团队
小明clone了小红的远程仓库到本地,小明对仓库文件进行修改,小明要想将修改推送到小红的远程仓库,需要小红先邀请小明加入团队。小明登录第三方远程仓库平台访问邀请链接。
4.5 拉取
- 拉取远程仓库的分支到本地,不会修改本地仓库文件
git fetch [远程仓库地址别名] [远程分支名]
- 拉取并合并到本地仓库,相当于fetch+merge
git pull [远程仓库地址] [远程分支名]
4.6 SSH免密登录
- 进入当前系统用户的用户目录
$ cd
- 运行命令生成SSH密钥
$ ssh-keygen -t rsa -C [第三方远程仓库登录邮箱]
- 复制生成的密钥文件中的内容(.ssh/id_rsa.pub)
- 登录第三方远程仓库,新增SSH Key,粘贴密钥内容
- 复制仓库的SSH链接
- 回到本地Git Bash创建远程仓库地址
$ git remote add orgin_ssh [远程仓库的ssh连接]
4.7 Eclipse的Git操作
4.7.1 工程目录设为工作区
- 工程→右键→Team→Share Project→Git
4.7.2 设置忽略文件
- GitHub官网模板:
https://github.com/github/gitignore
https://github.com/github/gitignore/blob/master/Java.gitignore
- 新建一个Java.gitignore文件,在~/gitconfig中引入该文件
Java.gitignore
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
.classpath
.project
.settings
target
.gitconfig (注意:目录路径使用"/",不能用"\")
[user]
name = tang_g
email = tang_g@email.com
[core]
excludesfile = C:/Users/TANG/Java.gitignore
4.7.4 提交到本地库
- 工程→右键→Team→commit
4.7.5 推送到远程库
- 登录第三方远程仓库,新建一个仓库,复制https连接
- 工程→右键→Team→remote→push
4.7.6 克隆到本地
- import→project from git→clone uri
注意:选择第三个。第一个:由于gitignore没有提交eclipse相关配置文件,eclipse无法识别。第二个:会新建一个工程,clone的项目会作为工程的子目录文件
- 将工程转换为maven项目
工程→右键→configure→convert to maven project
4.7.7 创建和合并分支
新建分支
- 工程→右键→switch to→new branch
合并分支
- 从远程仓库拉取(pull)到本地
- 将远程分支检出为本地分支
工程→右键→switch to→other→选择remote tracking的新建分支→check out→check out as new local branch
- 检查代码无误,切换回master,merge新分支,commit到本地库,push到远程库。
5. Gitlab 服务器搭建
可以利用Gitlab搭建自己的远程仓库,类似于GitHub。
5.1 Gitlab 官网
首页:https://about.gitlab.com/
安装说明:https://about.gitlab.com/installation/
Gitlab-ce:https://packages.gitlab.com/gitlab/gitlab-ce/packages/el/7/gitlab-ce-10.8.2-ce.0.el7.x86_64.rpm
可以先下载Gitlab-ce安装包,减少yum安装时间
5.2 安装命令
sudo rpm -ivh /opt/gitlab-ce-10.8.2-ce.0.el7.x86_64.rpm
sudo yum install -y curl policycoreutils-python openssh-server cronie
sudo lokkit -s http -s ssh
sudo yum install postfix
sudo service postfix start
sudo chkconfig postfix on
curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash
sudo EXTERNAL_URL="http://gitlab.example.com" yum -y install gitlab-ce
完成后重启系统,然后进行初始化(gitlab-ctl reconfigure),输入ip地址进行访问
5.3 基本操作
初始化配置
gitlab-ctl reconfigure
启动gitlab服务
gitlab-ctl start
启动gitlab服务
gitlab-ctl stop