为什么需要版本控制?
本地版本控制系统 许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别。这么做唯一的 好处就是简单,但是特别容易犯错。有时候会混淆所在的工作目录,一不小心会写错文件或者覆盖意想外的文件。
有了又怎么样?
l 自动生成备份
l 知道改动的地方
l 随时回滚
SVN
集中式的版本控制系统,只有一个中央数据仓库,如果中央数据仓库挂了或者不可访问,所有的使用者无法使用SVN,无法进行提交或备份文件。
Git
分布式的版本控制系统,在每个使用者电脑上就有一个完整的数据仓库,没有网络依然可以使用Git。当然为了习惯及团队协作,会将本地数据同步到Git服务器或者GitHub等代码仓库。
官网:https://git-scm.com
git是一个分布式版本控制软件,最初由林纳斯·托瓦兹(Linus Torvalds)创作,于2005年以GPL发布。最初目的是为更好地管理Linux内核开发而设计。
Git 官方中文手册 https://git-scm.com/book/zh/v2
自2002年开始,林纳斯·托瓦兹决定使用BitKeeper作为Linux内核主要的版本控制系统用以维护代码。因为BitKeeper为专有软件,这个决定在社区中长期遭受质疑。在Linux社区中,特别是理查德·斯托曼与自由软件基金会的成员,主张应该使用开放源代码的软件来作为Linux核心的版本控制系统。林纳斯·托瓦兹曾考虑过采用现成软件作为版本控制系统(例如Monotone),但这些软件都存在一些问题,特别是性能不佳。现成的方案,如CVS的架构,受到林纳斯·托瓦兹的批评。
2005年,安德鲁·垂鸠写了一个简单程序,可以连接BitKeeper的存储库,BitKeeper著作权拥有者拉里·麦沃伊认为安德鲁·垂鸠对BitKeeper内部使用的协议进行逆向工程,决定收回无偿使用BitKeeper的授权。Linux内核开发团队与BitMover公司进行蹉商,但无法解决他们之间的歧见。林纳斯·托瓦兹决定自行开发版本控制系统替代BitKeeper,以十天的时间,编写出第一个git版本。
[root@gitlab ~]# rpm -qa centos-release centos-release-7-2.1511.el7.centos.2.10.x86_64 [root@gitlab ~]# uname -a Linux gitlab 3.10.0-327.el7.x86_64 #1 SMP Thu Nov 19 22:10:57 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux [root@gitlab ~]# getenforce Disabled [root@gitlab ~]# systemctl status firewalld.service ● firewalld.service - firewalld - dynamic firewall daemon Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled) Active: inactive (dead) |
centos 自带git [root@gitlab ~]# rpm -qa git git-1.8.3.1-11.el7.x86_64
安装方法 yum install git -y |
编译安装可以安装较新版本的git
Git下载地址: https://github.com/git/git/releases
安装依赖关系 yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel
编译安装 tar -zxf git-2.0.0.tar.gz cd git-2.0.0 make configure ./configure --prefix=/usr make make install |
命令集 git config --global user.name "wuhuang" #配置git使用用户 git config --global user.email "xxxxxxxxxxx@163.com" #配置git使用邮箱 git config --global color.ui true #语法高亮 git config --list #查看全局配置
配置结果 [root@gitlab ~]# git config --list user.name=wuhuang user.email=xxxxxxxxxxx@163.com color.ui=true
生成的配置文件 [root@gitlab ~]# cat .gitconfig [user] name = wuhuang email = xxxxxxxxxxx@163.com [color] ui = true |
使用Git时需要获取帮助,有三种方法可以找到Git命令的使用手册: git help <verb> git <verb> --help man git-<verb>
例如:要想获得配置命令的帮助手册,执行 git help config |
mkdir git_data # 创建目录 cd git_data/ # 进入目录 git init # 初始化 git status # 查看工作区状态
操作过程 [root@gitlab ~]# mkdir git_data [root@gitlab ~]# cd git_data/ [root@gitlab git_data]# git init 初始化空的 Git 版本库于 /root/git_data/.git/ [root@gitlab git_data]# git status # 位于分支 master # # 初始提交 # 无文件要提交(创建/拷贝文件并使用 "git add" 建立跟踪)
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 ├── info │ └── exclude ├── objects │ ├── info │ └── pack └── refs ├── heads └── tags
9 directories, 13 files |
命令 | 命令说明 | 命令 | 命令说明 |
add | 添加文件内容至索引 | log | 显示提交日志 |
bisect | 通过二分查找定位引入 bug 的变更 | merge | 合并两个或更多开发历史 |
branch | 列出、创建或删除分支 | mv | 移动或重命名一个文件、目录或符号链接 |
checkout | 检出一个分支或路径到工作区 | pull | 获取并合并另外的版本库或一个本地分支 |
clone | 克隆一个版本库到一个新目录 | push | 更新远程引用和相关的对象 |
commit | 记录变更到版本库 | rebase | 本地提交转移至更新后的上游分支中 |
diff | 显示提交之间、提交和工作区之间等的差异 | reset | 重置当前HEAD到指定状态 |
fetch | 从另外一个版本库下载对象和引用 | rm | 从工作区和索引中删除文件 |
grep | 输出和模式匹配的行 | show | 显示各种类型的对象 |
init | 创建一个空的 | status | 显示工作区状态 |
Git | 版本库或重新初始化一个已存在的版本库 | tag | 创建、列出、删除或校验一个GPG签名的 tag 对象 |
文件的状态变化周期
命令集 touch README git status git add README git status git commit -m 'first commit' #→git commit提交暂存文件至版本库 命令说明: git add * 添加到暂存区域 git commit 提交git仓库 -m 后面接上注释信息,内容关于本次提交的说明,方便自己或他人查看 修改或删除原有文件
创建文件 [root@gitlab git_data]# touch README [root@gitlab git_data]# git status # 位于分支 master # # 初始提交 # # 未跟踪的文件: # (使用 "git add <file>..." 以包含要提交的内容) # # README 提交为空,但是存在尚未跟踪的文件(使用 "git add" 建立跟踪)
添加文件跟踪——由工作目录提交到暂存区域 [root@gitlab git_data]# git add README [root@gitlab git_data]# git status # 位于分支 master # # 初始提交 # # 要提交的变更: # (使用 "git rm --cached <file>..." 撤出暂存区) # # 新文件: README #
由暂存区提交到本地仓库 [root@gitlab git_data]# git commit -m 'first commit' [master(根提交) 4ce5110] first commit 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 README |
常规方法 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. |
命令说明: 没有添加到暂存区的数据直接rm删除即可。 已经添加到暂存区数据: git rm --cached database #→将文件从git暂存区域的追踪列表移除(并不会删除当前工作目录内的数据文件) git rm -f database #→将文件数据从git暂存区和工作目录一起删除
命令实践: 创建新文件 [root@gitlab git_data]# touch test [root@gitlab git_data]# ls README test [root@gitlab git_data]# git status # 位于分支 master # 未跟踪的文件: # (使用 "git add <file>..." 以包含要提交的内容) # # test 提交为空,但是存在尚未跟踪的文件(使用 "git add" 建立跟踪) 将文件添加到暂存区域 [root@gitlab git_data]# git add test [root@gitlab git_data]# git status # 位于分支 master # 要提交的变更: # (使用 "git reset HEAD <file>..." 撤出暂存区) # # 新文件: test # 将文件从git暂存区域的追踪列表移除(方法1) [root@gitlab git_data]# git rm --cached test rm 'test' [root@gitlab git_data]# git status # 位于分支 master # 未跟踪的文件: # (使用 "git add <file>..." 以包含要提交的内容) # # test 提交为空,但是存在尚未跟踪的文件(使用 "git add" 建立跟踪) 将文件从git暂存区域的追踪列表移除(方法2) [root@gitlab git_data]# git add test [root@gitlab git_data]# git reset HEAD test [root@gitlab git_data]# git status # 位于分支 master # 未跟踪的文件: # (使用 "git add <file>..." 以包含要提交的内容) # # test 提交为空,但是存在尚未跟踪的文件(使用 "git add" 建立跟踪) 将文件数据从git暂存区和工作目录一起删除 [root@gitlab git_data]# git add test [root@gitlab git_data]# git status # 位于分支 master # 要提交的变更: # (使用 "git reset HEAD <file>..." 撤出暂存区) # # 新文件: test # [root@gitlab git_data]# git rm -f test rm 'test' [root@gitlab git_data]# ls README |
l 没有添加到暂存区的数据直接mv/rename改名即可。 l 已经添加到暂存区数据: git mv README NOTICE |
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 | 提交说明。 | %h | 提交对象的简短SHA-1哈希字串。 |
%cd | 提交日期。 | %T | 树对象的完整SHA-1哈希字串。 |
%an | 作者的名字。 | %t | 树对象的简短SHA-1哈希字串。 |
%cn | 提交者的姓名。 | %P | 父对象的完整SHA-1哈希字串。 |
%ce | 提交者的电子邮件。 | %p | 父对象的简短SHA-1哈希字串。 |
%H | 提交对象的完整SHA-1哈希字串。 | %ad | 作者的修订时间。 |
命令实践 [root@gitlab git_data]# git log -2 commit 7e142db5e0100c7cd71a2663ed0926c552f3f59c Author: wuhuang <xxxxxxxxxxx@163.com> Date: Wed Mar 21 09:24:57 2018 +0800
wuhuang
commit f70785716ddd65e83dca6a2f4d8cea722ae61de2 Author: wuhuang <xxxxxxxxxxx@163.com> Date: Wed Mar 21 09:24:18 2018 +0800
first commit
[root@gitlab git_data]# git log --pretty=oneline 7e142db5e0100c7cd71a2663ed0926c552f3f59c wuhuang f70785716ddd65e83dca6a2f4d8cea722ae61de2 first commit [root@gitlab git_data]# git log --pretty=fomat:"%h %cn" fomat:7e142db wuhuang fomat:f707857 wuhuang |
Git服务程序中有一个叫做HEAD的版本指针,当用户申请还原数据时,其实就是将HEAD指针指向到某个特定的提交版本,但是因为Git是分布式版本控制系统,为了避免历史记录冲突,故使用了SHA-1计算出十六进制的哈希字串来区分每个提交版本,另外默认的HEAD版本指针会指向到最近的一次提交版本记录,而上一个提交版本会叫HEAD^,上上一个版本则会叫做HEAD^^,当然一般会用HEAD~5来表示往上数第五个提交版本。
git reset --hard HEAD^ #→还原历史提交版本上一次 git reset --hard 3de15d4 #→找到历史还原点的SHA-1值后,就可以还原(值不写全,系统会自动匹配) 还原数据 [root@gitlab git_data]# git reset --hard f70785716 HEAD 现在位于 f707857 first commit [root@gitlab git_data]# git log commit f70785716ddd65e83dca6a2f4d8cea722ae61de2 Author: wuhuang <xxxxxxxxxxx@163.com> Date: Wed Mar 21 09:24:18 2018 +0800
first commit
|
什么是未来数据?就是你还原到历史数据了,但是你后悔了,想撤销更改,但是git log已经找不到这个版本了。
git reflog #→查看未来历史更新点
[root@gitlab git_data]# git reflog f707857 HEAD@{0}: reset: moving to f70785716 4ce5110 HEAD@{1}: reset: moving to 4ce5110bf3 7e142db HEAD@{2}: commit: wuhuang f707857 HEAD@{3}: commit: first commit 4ce5110 HEAD@{4}: commit (initial): first commit |
前面回滚使用的是一串字符串,又长又难记。使用标签就会方便很多。
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 tag v2 [root@gitlab git_data]# git show v2 commit f70785716ddd65e83dca6a2f4d8cea722ae61de2 Author: wuhuang <xxxxxxxxxxx@163.com> Date: Wed Mar 21 09:24:18 2018 +0800
first commit
diff --git a/README b/README index e69de29..190a180 100644 --- a/README +++ b/README @@ -0,0 +1 @@ +123 [root@gitlab git_data]# git reset --hard v2 HEAD 现在位于 f707857 first commit |
git diff可以对比当前文件与仓库已保存文件的区别,知道了对README作了什么修改
后,再把它提交到仓库就放?多了。
git diff README |
在实际的项目开发中,尽量保证master分支稳定,仅用于发布新版本,平时不要随便直接修改里面的数据文件。
那在哪干活呢?干活都在dev分支上。每个人从dev分支创建自己个人分支,开发完合并到dev分支,最后dev分支合并到master分支。所以团队的合作分支看起来会像下图那样。
l git branch linux #→创建分支 l git checkout linux #→切换分支 l git branch #→查看当前分支情况,当前分支前有*号
[root@gitlab git_data]# git branch * master [root@gitlab git_data]# git branch linux [root@gitlab git_data]# git branch linux * master [root@gitlab git_data]# git checkout linux 切换到分支 'linux' [root@gitlab git_data]# git branch * linux master |
想把Linux的工作成果合并到master分支上 先切换到master分支 git merge linux #→合并Linux分支至master 查看合并的文件 git branch -d linux #→确认合并完成后,可以放心地删除Linux分支 |
同时修改master和Linux分支同一个文件并提交,最后merge。
查看合并结果
模拟分支冲突 # 在master修改,提交 [root@gitlab git_data]# echo "master content" >>README [root@gitlab git_data]#git commit -a -m "master content" [master b52cc77] master content 1 file changed, 1 insertion(+)
# 切换到linux分支修改提交 [root@gitlab git_data]# git checkout linux 切换到分支 'linux' [root@gitlab git_data]# cat README 1 linux branch [root@gitlab git_data]# echo "linux content" >>README [root@gitlab git_data]# git commit -a -m "linux content" [linux cb72c04] linux content 1 file changed, 1 insertion(+)
# 回到master分支尝试自动合并 [root@gitlab git_data]# git checkout master 切换到分支 'master' [root@gitlab git_data]# git merge linux 自动合并 README 冲突(内容):合并冲突于 README 自动合并失败,修正冲突然后提交修正的结果。
解决冲突 [root@gitlab git_data]# vim README 1 linux branch linux content [root@gitlab git_data]# git commit -a -m "hebingshibai content" [master 068b921] hebingshibai content [root@gitlab git_data]# git log |
因为之前已经合并了linux分支,所以现在看到它在列表中。 在这个列表中分支名字前没有 * 号的分支通常可以使用 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 选项强制删除它。 |
windows 上git软件网站 https://git-for-windows.github.io
软件下载地址:https://github.com/git-for-windows/git/releases/download/v2.15.1.windows.2/Git-2.15.1.2-64-bit.exe
软件安装默认即可。
创建新的仓库
定义仓库的路径
添加用户信息(在 git bash中)
default@Hzs-Desktop MINGW64 /i/git_data (master) $ git config --global user.email "wuhuang@xxxxxxxxxxx@163.com"
default@Hzs-Desktop MINGW64 /i/git_data (master) $ git config --global user.name "wuhuang" |
在git Gui 中添加用户信息,添加一次就可
在页面中将数据配置好即可使用
查看历史数据
前面我们已经知道Git人人都是中心,那他们怎么交互数据呢?
l 使用GitHub或者码云等公共代码仓库
l 使用GitLab私有仓库
官方安装文档 https://about.gitlab.com/installation/
国内软件镜像站 https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/
机器内存给大点 yum -y localinstall gitlab-ce-9.1.4-ce.0.el7.x86_64.rpm gitlab-ctl reconfigure #→初始化,就执行一次 gitlab-ctl status
gitlab-ctl status/stop/start 通过浏览器访问页面10.0.0.63,设置初始密码,其他操作类似GitHUB。 账户:root 密码自己设置为12345678(八位数即可) |
第一次访问,创建密码
进行登陆,用户名为root,密码为12345678
创建一个新的项目
定义项目的名称
创建完成后会提示没有添加ssh密钥
在服务器上创建ssh密钥 使用ssh-ketgen 命令 [root@gitlab ~]# ssh-keygen [root@gitlab ~]# cat /root/.ssh/id_rsa.pub ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCr+4fZv83jQQDCngjmuiJFw0H0nGHfACVuxgZLszqla4VFZIKOCyXzexhhHW+vH7Us03AXssL7gFxSZg68bz+shBXz2OhFulwisdIQqbWFqBuWAthSrKQlnWIFzM9lzXX/ffI6xYlHP7i8c+Nz3C0Irm7lnP3M5IJpYIuCDuKc0NSGjQpxpqMYkzNqGCkYCk+rB8I/aZv9u49iOCD6I0WkEpbL2hzoR7gUMi/Wyy6gKag1Cy3Omi7FS19dGofITmG6XlFDcRzRH9pz8eBzbzlKmX1GjsndEELCImHLKjmRmvopdF5J7b1wfWYcHfS+Z+SSx2rCeIF4zxzIfO+osnkD root@gitlab |
将密钥添加到web界面的用户中
Command line instructions Git global setup git config --global user.name "Administrator" git config --global user.email "admin@example.com" Create a new repository git clone git@gitlab.example.com:root/clsn.git cd clsn touch README.md git add README.md git commit -m "add README" git push -u origin master Existing folder cd existing_folder git init git remote add origin git@gitlab.example.com:root/clsn.git git add . git commit -m "Initial commit" git push -u origin master Existing Git repository cd existing_repo git remote rename origin old-origin git remote add origin git@gitlab.example.com:root/clsn.git git push -u origin --all git push -u origin --tags |
[root@gitlab ~]# git clone git@10.0.0.63:root/wuhuang.git 正克隆到 'wuhuang'... warning: 您似乎克隆了一个空版本库。
创建文件并推到远端git仓库 [root@gitlab ~]# cd wuhuang/ [root@gitlab wuhuang]# touch README.md [root@gitlab wuhuang]# git add README.md [root@gitlab wuhuang]# git commit -m "add README" [master(根提交) 128444a] add README 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 README.md
[root@gitlab wuhuang]# git push -u origin master Counting objects: 3, done. Writing objects: 100% (3/3), 211 bytes | 0 bytes/s, done. Total 3 (delta 0), reused 0 (delta 0) To git@10.0.0.63:root/wuhuang.git * [new branch] master -> master 分支 master 设置为跟踪来自 origin 的远程分支 master。
|
推送完成后能够在web界面中查看并添加内容
拉取文件 [root@gitlab wuhuang]# git pull remote: Counting objects: 3, done. remote: Compressing objects: 100% (2/2), done. remote: Total 3 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (3/3), done. 来自 10.0.0.63:root/wuhuang 128444a..22c72d6 master -> origin/master 更新 128444a..22c72d6 Fast-forward README.md | 9 +++++++++ 1 file changed, 9 insertions(+)
查看文件 [root@gitlab wuhuang]# cat README.md # 1. 第一章 git
```html git config --global user.name "wuhuang" #配置git使用用户 git config --global user.email "xxxxxxxxxxx@163.com" #配置git使用邮箱 git config --global color.ui true #语法高亮 git config --list #查看全局配置 ``` |
开机自启动gitlab gitlab-ctl start #→再次开机之后需重新启动(在初始化之后gitlab自动启动) chmod +x /etc/rc.d/rc.local echo 'gitlab-ctl start' >>/etc/rc.local |
原文地址:http://blog.51cto.com/12805107/2089757