1、Git历史
自2002年开始,林纳斯·托瓦兹决定使用BitKeeper作为Linux内核主要的版本控制系统用以维护代码。因为BitKeeper为专有软件,这个决定在社区中长期遭受质疑。在Linux社区中,特别是理查德·斯托曼与自由软件基金会的成员,主张应该使用开放源代码的软件来作为Linux核心的版本控制系统。林纳斯·托瓦兹曾考虑过采用现成软件作为版本控制系统(例如Monotone),但这些软件都存在一些问题,特别是性能不佳。现成的方案,如CVS的架构,受到林纳斯·托瓦兹的批评。
2005年,安德鲁·垂鸠写了一个简单程序,可以连接BitKeeper的存储库,BitKeeper著作权拥有者拉里·麦沃伊认为安德鲁·垂鸠对BitKeeper内部使用的协议进行逆向工程,决定收回无偿使用BitKeeper的授权。Linux内核开发团队与BitMover公司进行蹉商,但无法解决他们之间的歧见。林纳斯·托瓦兹决定自行开发版本控制系统替代BitKeeper,以十天的时间,编写出第一个git版本
2、git用来干什么?
不知道你工作的时候有没有遇到这样的情况:
比如说,做BIM建模,你手中有一份模型初稿,但现在需要在上面进行修改。
1、你怕修改之后万一出现什么错误,把原来的文件也弄坏了;
2、你修改到一定程度,改错了,想撤销,但你不小心点了保存,保存之后是不能撤销的。
于是你不得不复制出一个副本,比如:
3、安装git
1 安装环境
首先关闭防火墙与selinux
[root@git ~]# rpm -qa centos-release
centos-release-7-4.1708.el7.centos.x86_64
2 Yum安装Git
centos 自带git
[root@git ~]# rpm -qa git git-1.8.3.1-11.el7.x86_64
安装方法
[root@git ~]# yum install git -y
4、初次运行 Git 前的配置
配置过程
[root@gitlab ~]# git config --global user.name "newrain" #配置git使用用户 [root@gitlab ~]# git config --global user.email "newrain@aliyun.com" #配置git使用邮箱 [root@gitlab ~]# git config --global color.ui true #语法高亮 [root@gitlab ~]# git config --list # 查看全局配置 user.name=newrain user.mail=newrain@aliyun.com color.ui=true
1.获取帮助
使用Git时需要获取帮助,有三种方法可以找到Git命令的使用手册:
git help <verb> git <verb> --help man git-<verb>例如,要想获得配置命令的手册,执行
git help config
5 、获取 Git 仓库(初始化仓库)
1、首先我们要创建一个裸(空的)库
[root@gitlab ~]# useradd git
[root@gitlab ~]# passwd git
[root@gitlab ~]# mkdir /git-root/
[root@gitlab ~]# cd /git-root/
[root@gitlab git-root]# git init --bare shell.git
Initialized empty Git repository in /git-root/shell.git/
[root@gitlab git-root]# chown -R git:git shell.git
2、打开另一台服务器,也要关闭防火墙和selinux,还要下载git(和上面步骤一样)作为本地仓库使用
创建本地仓库
[root@gitlab opt]# ssh-keygen
[root@gitlab opt]# ssh-copy-id git@10.12.153.161
[root@gitlab opt]# git clone git@10.12.153.161:/git-root/shell.git
[root@gitlab opt]# ls
rh shellcd
[root@gitlab opt]# cd shell/
[root@gitlab shell]# vim test1.sh (自己往文件随便写点东西)
[root@gitlab shell]# git add test1.sh
[root@gitlab shell]# git commit -m 'KX'
[master (root-commit) 33c5fbf] KX
1 file changed, 2 insertions(+)
create mode 100644 test1.sh
[root@gitlab shell]# git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 230 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@10.12.153.160:/git-root/shell.git
* [new branch] master -> master
[root@gitlab shell]#
[root@git objects]# tree (在上一台机器的/root/shell/objects下运行)
[root@git objects]# tree
.
├── 0c
│ └── 48137336be8e3203660633517a1ad2aace8ffa
├── a0
│ └── 05da6d5b81ecdcc10d247c7f4c2c7f4ad1f059
├── c5
│ └── 1e7ee650766ca34b21cd852f5a628de8de3de0
├── info
└── pack
5 directories, 3 files
#显示文件内容
[root@git objects]# git cat-file -p 0c4813733一定要开心!!!
# 显示文件类型
[root@git objects]# git cat-file -t 0c4813733
blob# 显示文件大小
[root@git objects]# git cat-file -s 0c4813733
25
6 、Git命令常规操作
常用命令说明
命令 | 命令说明 |
---|---|
#add | 添加文件内容至索引 |
bisect | 通过二分查找定位引入 bug 的变更 |
#branch | 列出、创建或删除分支 |
#checkout | 检出一个分支或路径到工作区 |
#clone | 克隆一个版本库到一个新目录 |
#commit | 从暂存库更到版本库 |
#diff | 显示提交之间、提交和工作区之间等的差异 |
fetch | 从另外一个版本库下载对象和引用 |
grep | 输出和模式匹配的行 |
#init | 创建一个空的(本地库或远程仓库) |
#log | 显示提交日志 |
#merge | 合并两个或更多开发历史 |
#mv | 移动或重命名一个文件、目录或符号链接 |
#pull | 获取并合并另外的版本库或一个本地分支 |
#push | 更新远程引用和相关的对象 |
rebase | 本地提交转移至更新后的上游分支中 |
#reset | 重置当前HEAD到指定状态 |
#rm | 从工作区和索引中删除文件 |
show | 显示各种类型的对象 |
#status | 显示工作区状态 |
#tag | 创建、列出、删除或校验一个GPG签名的 tag 对象 |
1.6.1 创建文件
[root@gitlab git_data]# touch README [root@gitlab git_data]# git status # 位于分支 master # # 初始提交 # # 未跟踪的文件: # (使用 "git add <file>..." 以包含要提交的内容) # # README 提交为空,但是存在尚未跟踪的文件(使用 "git add" 建立跟踪) --- # On branch master # # Initial commit # # Untracked files: # (use "git add <file>..." to include in what will be committed) # # README nothing added to commit but untracked files present (use "git add" to track)
添加文件跟踪
[root@gitlab git_data]# git add ./* [root@gitlab git_data]# git status # 位于分支 master # # 初始提交 # # 要提交的变更: # (使用 "git rm --cached <file>..." 撤出暂存区) # # 新文件: README # --- # On branch master # # Initial commit # # Changes to be committed: # (use "git rm --cached <file>..." to unstage) # # new file: README #
文件会添加到.git的隐藏目录
[root@gitlab git_data]# tree .git/ .git/ ├── branches ├── config ├── description ├── HEAD ├── hooks │ ├── applypatch-msg.sample │ ├── commit-msg.sample │ ├── post-update.sample │ ├── pre-applypatch.sample │ ├── pre-commit.sample │ ├── prepare-commit-msg.sample │ ├── pre-push.sample │ ├── pre-rebase.sample │ └── update.sample ├── index ├── info │ └── exclude ├── objects │ ├── e6 │ │ └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391 │ ├── info │ └── pack └── refs ├── heads └── tags
由工作区提交到本地仓库
[root@gitlab git_data]# git commit -m 'first commit' [master(根提交) bb963eb] first commit 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 README查看git的状态
[root@gitlab git_data]# git status # 位于分支 master 无文件要提交,干净的工作区 # On branch master nothing to commit, working directory clean提交后的git目录状态
[root@gitlab git_data]# tree .git/ .git/ ├── branches ├── COMMIT_EDITMSG ├── config ├── description ├── HEAD ├── hooks │ ├── applypatch-msg.sample │ ├── commit-msg.sample │ ├── post-update.sample │ ├── pre-applypatch.sample │ ├── pre-commit.sample │ ├── prepare-commit-msg.sample │ ├── pre-push.sample │ ├── pre-rebase.sample │ └── update.sample ├── index ├── info │ └── exclude ├── logs │ ├── HEAD │ └── refs │ └── heads │ └── master ├── objects │ ├── 54 │ │ └── 3b9bebdc6bd5c4b22136034a95dd097a57d3dd │ ├── bb │ │ └── 963eb32ad93a72d9ce93e4bb55105087f1227d │ ├── e6 │ │ └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391 │ ├── info │ └── pack └── refs ├── heads │ └── master └── tags
1.6.2 添加新文件
git add * 添加到暂存区域 git commit 提交git仓库 -m 后面接上注释信息,内容关于本次提交的说明,方便自己或他人查看修改或删除原有文件
常规方法
git add * git commit简便方法
git commit -a -m "注释信息"-a 表示直接提交
Tell the command to automatically stage files that have been modified and deleted, but new files you have not told Git about are not affected.
1.6.3 删除git内的文件
命令说明:
• 没有添加到暂存区的数据直接rm删除即可。
• 已经添加到暂存区数据:
git rm --cached database
#→将文件从git暂存区域的追踪列表移除(并不会删除当前工作目录内的数据文件)
git rm -f database
#→将文件数据从git暂存区和工作目录一起删除
命令实践:
# 创建新文件 [root@gitlab git_data]# touch 123 [root@gitlab git_data]# git status # 位于分支 master # 未跟踪的文件: # (使用 "git add <file>..." 以包含要提交的内容) # # 123 提交为空,但是存在尚未跟踪的文件(使用 "git add" 建立跟踪) --- # On branch master # Untracked files: # (use "git add <file>..." to include in what will be committed) # # 123 nothing added to commit but untracked files present (use "git add" to track)
# 将文件添加到暂存区域
[root@gitlab git_data]# git add 123 [root@gitlab git_data]# git status # 位于分支 master # 要提交的变更: # (使用 "git reset HEAD <file>..." 撤出暂存区) # # 新文件: 123 --- # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: 123
# 删除文件
[root@gitlab git_data]# rm 123 -f [root@gitlab git_data]# ls README [root@gitlab git_data]# git status # 位于分支 master # 要提交的变更: # (使用 "git reset HEAD <file>..." 撤出暂存区) # # 新文件: 123 # # 尚未暂存以备提交的变更: # (使用 "git add/rm <file>..." 更新要提交的内容) # (使用 "git checkout -- <file>..." 丢弃工作区的改动) # # 删除: 123 # --- # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: 123 # # 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: 123 [root@gitlab git_data]# git reset HEAD ./* [root@gitlab git_data]# git status # 位于分支 master 无文件要提交,干净的工作区 --- # On branch master nothing to commit, working directory clean
1.6.4 重命名暂存区数据
• 没有添加到暂存区的数据直接mv/rename改名即可。
• 已经添加到暂存区数据:
git mv README NOTICE[root@gitlab git_data]# git mv README notice [root@gitlab git_data]# git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # renamed: README -> notice #
1.6.5 查看历史记录
• git log #→查看提交历史记录
• git log -2 #→查看最近几条记录
• git log -p -1 #→-p显示每次提交的内容差异,例如仅查看最近一次差异
• git log --stat -2 #→--stat简要显示数据增改行数,这样能够看到提交中修改过的内容,对文件添加或移动的行数,并在最后列出所有增减行的概要信息
• git log --pretty=oneline #→--pretty根据不同的格式展示提交的历史信息
• git log --pretty=fuller -2 #→以更详细的模式输出提交的历史记录
• git log --pretty=fomat:"%h %cn" #→查看当前所有提交记录的简短SHA-1哈希字串与提交着的姓名。
使用format参数来指定具体的输出格式
格式 | 说明 |
---|---|
%s | 提交说明。 |
%cd | 提交日期。 |
%an | 作者的名字。 |
%cn | 提交者的姓名。 |
%ce | 提交者的电子邮件。 |
%H | 提交对象的完整SHA-1哈希字串。 |
%h | 提交对象的简短SHA-1哈希字串。 |
%T | 树对象的完整SHA-1哈希字串。 |
%t | 树对象的简短SHA-1哈希字串。 |
%P | 父对象的完整SHA-1哈希字串。 |
%p | 父对象的简短SHA-1哈希字串。 |
%ad | 作者的修订时间。 |
命令实践
[root@gitlab git_data]# git log commit f5b79552635a7dc60afc35c99c1170366d8c5f6b Author: newrain <newrain@aliyun.com> Date: Sat May 11 21:29:21 2019 -0700 456 commit e9ed8b38a0052cdcd85ecee833ea8198b077f881 Author: newrain <root@vmdesk.localdomain> Date: Sat May 11 21:21:12 2019 -0700 commit 123 commit 9d394114177b8da9e452d001ec610e9c45ceede3 Author: newrain <root@vmdesk.localdomain> Date: Sat May 11 20:19:23 2019 -0700 first commit1.6.6 还原历史数据
Git服务程序中有一个叫做HEAD的版本指针,当用户申请还原数据时,其实就是将HEAD指针指向到某个特定的提交版本,但是因为Git是分布式版本控制系统,为了避免历史记录冲突,故使用了SHA-1计算出十六进制的哈希字串来区分每个提交版本,另外默认的HEAD版本指针会指向到最近的一次提交版本记录,而上一个提交版本会叫HEAD^,上上一个版本则会叫做HEAD^^,当然一般会用HEAD~5来表示往上数第五个提交版本。
git reset --hard hash
git reset --hard HEAD^ #→还原历史提交版本上一次
git reset --hard 3de15d4 #→找到历史还原点的SHA-1值后,就可以还原(值不写全,系统
会自动匹配)
测试命令
[root@gitlab git_data]# git log commit f5b79552635a7dc60afc35c99c1170366d8c5f6b Author: newrain <newrain@aliyun.com> Date: Sat May 11 21:29:21 2019 -0700 456 commit e9ed8b38a0052cdcd85ecee833ea8198b077f881 Author: newrain <root@vmdesk.localdomain> Date: Sat May 11 21:21:12 2019 -0700 commit 123 commit 9d394114177b8da9e452d001ec610e9c45ceede3 Author: newrain <root@vmdesk.localdomain> Date: Sat May 11 20:19:23 2019 -0700 first commit
还原数据
[root@gitlab git_data]# git reset --hard e9ed8b38a HEAD is now at e9ed8b3 commit 123 HEAD 现在位于 e9ed8b3 commit 123 # 查看数据 [root@gitlab git_data]# ls 123 README
1.6.7 还原未来数据
什么是未来数据?就是你还原到历史数据了,但是你后悔了,想撤销更改,但是git log已经找不到这个版本了。
git reflog #→查看未来历史更新点
测试命令
[root@gitlab git_data]# git reflog e9ed8b3 HEAD@{0}: reset: moving to e9ed8b38a f5b7955 HEAD@{1}: commit: 456 e9ed8b3 HEAD@{2}: commit: commit 123 9d39411 HEAD@{3}: commit (initial): first commit [root@gitlab git_data]#
1.6.8 标签使用
前面回滚使用的是一串字符串,又长又难记。
git tag v1.0 #→当前提交内容打一个标签(方便快速回滚),每次提交都可以打个tag。
git tag #→查看当前所有的标签
git show v1.0 #→查看当前1.0版本的详细信息
git tag v1.2 -m "version 1.2 release is test" #→创建带有说明的标签,-a指定标签名字,-m指定说明文字
git tag -d v1.0 #→我们为同一个提交版本设置了两次标签,删除之前的v1.0
测试命令
[root@gitlab git_data]# git reset --hard e9ed8b38a HEAD is now at e9ed8b3 commit 123 [root@gitlab git_data]# git reset --hard V1.0 HEAD is now at e9ed8b3 add test dir [root@gitlab git_data]# git tag v20171129 [root@gitlab git_data]# git tag v20171129
1.6.9 对比数据
git diff可以对比当前文件与仓库已保存文件的区别,知道了对README作了什么修改
后,再把它提交到仓库就放⼼多了。
git diff README git diff --name-only HEAD HEAD^ git diff --name-only head_id head_id2
1.7 分支结构
在实际的项目开发中,尽量保证master分支稳定,仅用于发布新版本,平时不要随便直接修改里面的数据文件。
那在哪干活呢?干活都在dev分支上。每个人从dev分支创建自己个人分支,开发完合并到dev分支,最后dev分支合并到master分支。所以团队的合作分支看起来会像下图那样。
1.7.1 分支切换
[root@gitlab git_data]# git branch newrain [root@gitlab git_data]# git branch * master newrain [root@gitlab git_data]# git checkout newrain 切换到分支 'newrain' Switched to branch 'newrain' [root@gitlab git_data]# git branch master * newrain
在newrain 分支进行修改
[root@gitlab git_data]# cat README This is git_data readme [root@gitlab git_data]# echo '1901' >> README [root@gitlab git_data]# git add . [root@gitlab git_data]# git commit -m '1901' [newrain 4310e7e] 1901 1 file changed, 1 insertion(+) [root@gitlab git_data]# git status # On branch newrain nothing to commit, working directory clean --- # 位于分支 newrain 无文件要提交,干净的工作区
回到master分支
[root@gitlab git_data]# git checkout master Switched to branch 'master' 切换到分支 'master' [root@gitlab git_data]# cat README This is git_data readme [root@gitlab git_data]# git log -1 commit f5b79552635a7dc60afc35c99c1170366d8c5f6b Author: newrain <newrain@aliyun.com> Date: Sat May 11 21:29:21 2019 -0700 456
合并代码
[root@gitlab git_data]# git merge newrain Updating f5b7955..4310e7e Fast-forward README | 1 + 1 file changed, 1 insertion(+) [root@gitlab git_data]# git status # On branch master nothing to commit, working directory clean # 位于分支 master 无文件要提交,干净的工作区 [root@gitlab git_data]# cat README This is git_data readme 1901
1.7.2 合并失败解决
模拟冲突,在文件的同一行做不同修改
在master 分支进行修改
[root@gitlab git_data]# cat README This is git_data readme 1901 [root@gitlab git_data]# echo '1901-git' > README [root@gitlab git_data]# git commit -m 'newrain 1901-git' [master 4e6c548] newrain 1901-git 1 file changed, 1 insertion(+), 2 deletions(-)
切换到newrain分支
[root@gitlab git_data]# git checkout newrain Switched to branch 'newrain' [root@gitlab git_data]# cat README This is git_data readme 1901 [root@gitlab git_data]# echo 'newrain' >> README [root@gitlab git_data]# git commit -m '1901-git-check' # On branch newrain # 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: README # no changes added to commit (use "git add" and/or "git commit -a")
回到master分区,进行合并,出现冲突
[root@gitlab git_data]# git checkout master 切换到分支 'master' [root@gitlab git_data]# git merge linux 自动合并 README 冲突(内容):合并冲突于 README 自动合并失败,修正冲突然后提交修正的结果。
解决冲突
[root@gitlab git_data]# vim README This is git_data readme 1901 newrain meger test ti meger test master# 手工解决冲突
[root@gitlab git_data]# git commit -a -m "merge-ti-test" [master 2594b2380] merge-ti-test
1.7.3 删除分支
因为之前已经合并了newrain分支,所以现在看到它在列表中。 在这个列表中分支名字前没有 * 号的分支通常可以使用 git branch -d 删除掉;你已经将它们的工作整合到了另一个分支,所以并不会失去任何东西。
查看所有包含未合并工作的分支,可以运行 git branch --no-merged**:
git branch --no-merged testing
这里显示了其他分支。 因为它包含了还未合并的工作,尝试使用 git branch -d 命令删除它时会失败:
git branch -d testing error: The branch 'testing' is not fully merged. If you are sure you want to delete it, run 'git branch -D testing'.
如果真的想要删除分支并丢掉那些工作,如同帮助信息里所指出的,可以使用 -D 选项强制删除它。