关注【老男孩Linux】离大牛更近一步 一、关于版本控制 1.本地版本控制 本地版本控制系统 许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别。这么做唯一的好处就是简单,但是特别容易犯错。有时候会混淆所在的工作目录,一不小心会写错文件或者覆盖意想外的文件。 2.集中化的版本控制系统 如何让在不同系统上的开发者协同工作?于是,集中化的版本控制系统(Centralized Version Control Systems,简称 CVCS)应运而生。这类系统,诸如 CVS、Subversion 以及Perforce 等,都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。多年以来,这已成为版本控制系统的标准做法。 3.分布式版本控制系统 在这类系统中,像Git、Mercurial、Bazaar 以及 Darcs 等,客户端并不只提取最新版本的文件快照,而是把代码仓库完整地镜像下来。这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。 二、Git简介 官网:https://git-scm.com git是一个分布式版本控制软件,最初由林纳斯·托瓦兹(Linus Torvalds)创作,于2005年以GPL发布。最初目的是为更好地管理Linux内核开发而设计。 1.Git历史 自2002年开始,林纳斯·托瓦兹决定使用BitKeeper作为Linux内核主要的版本控制系统用以维护代码。因为BitKeeper为专有软件,这个决定在社区中长期遭受质疑。在Linux社区中,特别是理查德·斯托曼与自由软件基金会的成员,主张应该使用开放源代码的软件来作为Linux核心的版本控制系统。林纳斯·托瓦兹曾考虑过采用现成软件作为版本控制系统(例如Monotone),但这些软件都存在一些问题,特别是性能不佳。现成的方案,如CVS的架构,受到林纳斯·托瓦兹的批评。 2005年,安德鲁·垂鸠写了一个简单程序,可以连接BitKeeper的存储库,BitKeeper著作权拥有者拉里·麦沃伊认为安德鲁·垂鸠对BitKeeper内部使用的协议进行逆向工程,决定收回无偿使用BitKeeper的授权。Linux内核开发团队与BitMover公司进行蹉商,但无法解决他们之间的歧见。林纳斯·托瓦兹决定自行开发版本控制系统替代BitKeeper,以十天的时间,编写出第一个git版本。 三、安装Git 1.环境说明 [root@gitlab ~]# rpm -qa centos-release centos-release-7-4.1708.el7.centos.x86_64 [root@gitlab ~]# uname -a Linux gitlab 3.10.0-693.el7.x86_64 #1 SMP Tue Aug 22 21:09:27 UTC 2017 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) Docs: man:firewalld(1) # 本文使用的linux系统均为该系统 # 本文使用的windows系统为 Microsoft Windows [版本 10.0.15063] 2.Yum安装Git # centos 自带git [root@gitlab ~]# rpm -qa git git-1.8.3.1-11.el7.x86_64 # 安装方法 yum install git -y 3.编译安装 编译安装可以安装较新版本的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 前的配置 1.配置git 命令集 git config --global user.name "oldboy" #配置git使用用户 git config --global user.email "admin@oldboyedu.com" #配置git使用邮箱 git config --global color.ui true #语法高亮 git config --list # 查看全局配置 配置过程 [root@gitlab ~]# git config --global user.name "oldboy" #配置git使用用户 [root@gitlab ~]# git config --global user.email "admin@oldboyedu.com" #配置git使用邮箱 [root@gitlab ~]# git config --global color.ui true #语法高亮 [root@gitlab ~]# git config --list # 查看全局配置 user.name=oldboy user.email=admin@oldboyedu.com color.ui=true 生成的配置文件 [root@gitlab ~]# cat .gitconfig [user] name = oldboy email = admin@oldboyedu.com [color] ui = true 2.获取帮助 使用Git时需要获取帮助,有三种方法可以找到Git命令的使用手册: git help <verb> git <verb> --help man git-<verb> 例如,要想获得配置命令的手册,执行 git help config 五、获取Git仓库(初始化仓库) # 创建目录 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命令常规操作 常用命令说明
常用操作示意图 文件的状态变化周期 1.创建文件 [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 ./* [root@gitlab git_data]# git status # 位于分支 master # # 初始提交 # # 要提交的变更: # (使用 "git rm --cached <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 无文件要提交,干净的工作区 提交后的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 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. 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" 建立跟踪) # 将文件添加到暂存区域 [root@gitlab git_data]# git add 123 [root@gitlab git_data]# git status # 位于分支 master # 要提交的变更: # (使用 "git reset HEAD <file>..." 撤出暂存区) # # 新文件: 123 # 删除文件 [root@gitlab git_data]# rm 123 -f [root@gitlab git_data]# ls [root@gitlab git_data]# git status # 位于分支 master # 要提交的变更: # (使用 "git reset HEAD <file>..." 撤出暂存区) # # 新文件: 123 # # 尚未暂存以备提交的变更: # (使用 "git add/rm <file>..." 更新要提交的内容) # (使用 "git checkout -- <file>..." 丢弃工作区的改动) # # 删除: 123 # [root@gitlab git_data]# git reset HEAD ./* [root@gitlab git_data]# git status # 位于分支 master 无文件要提交,干净的工作区 4.重命名暂存区数据 • 没有添加到暂存区的数据直接mv/rename改名即可。 • 已经添加到暂存区数据: git mv README NOTICE 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参数来指定具体的输出格式:
命令实践: [root@gitlab git_data]# git log commit a409fc46f792228a8119705e9cc97c2a013534ab Author: oldboy <admin@oldboyedu.com> Date: Wed Nov 29 11:44:14 2017 +0800 test commit bb963eb32ad93a72d9ce93e4bb55105087f1227d Author: oldboy <admin@oldboyedu.com> Date: Wed Nov 29 10:57:02 2017 +0800 first commit 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 a409fc46f792228a8119705e9cc97c2a013534ab Author: oldboy <123@oldboyedu.com> Date: Wed Nov 29 11:44:14 2017 +0800 test commit bb963eb32ad93a72d9ce93e4bb55105087f1227d Author: oldboy <123@oldboyedu.com> Date: Wed Nov 29 10:57:02 2017 +0800 first commit 还原数据 [root@gitlab git_data]# git reset --hard bb963 HEAD 现在位于 bb963eb first commit # 查看数据 [root@gitlab git_data]# ls README 7.还原未来数据 什么是未来数据?就是你还原到历史数据了,但是你后悔了,想撤销更改,但是git log已经找不到这个版本了。 git reflog #→查看未来历史更新点 测试命令: [root@gitlab git_data]# git reflog bb963eb HEAD@{0}: reset: moving to bb963 a409fc4 HEAD@{1}: reset: moving to a409fc4 bb963eb HEAD@{2}: reset: moving to bb963 a409fc4 HEAD@{3}: commit: test bb963eb HEAD@{4}: commit (initial): first commit [root@gitlab git_data]# 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 0bdf2e7 HEAD is now at 0bdf2e7 modified README file [root@gitlab git_data]# git reset --hard V1.0 HEAD is now at a66370a add test dir [root@gitlab git_data]# git tag v20171129 [root@gitlab git_data]# git tag v20171129 9.对比数据 git diff可以对比当前文件与仓库已保存文件的区别,知道了对README作了什么修改后,再把它提交到仓库就放多了。 git diff README 七、分支结构 在实际的项目开发中,尽量保证master分支稳定,仅用于发布新版本,平时不要随便直接修改里面的数据文件。 那在哪干活呢?干活都在dev分支上。每个人从dev分支创建自己个人分支,开发完合并到dev分支,最后dev分支合并到master分支。所以团队的合作分支看起来会像下图那样。 1.分支切换 [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分支进行修改 [root@gitlab git_data]# cat README [root@gitlab git_data]# echo "2017年11月30日" >> README [root@gitlab git_data]# git add . [root@gitlab git_data]# git commit -m "2017年11月30日09点10分" [linux 5a6c037] 2017年11月30日09点10分 1 file changed, 1 insertion(+) [root@gitlab git_data]# git status # 位于分支 linux 无文件要提交,干净的工作区 回到master分支 [root@gitlab git_data]# git checkout master 切换到分支 'master' [root@gitlab git_data]# cat README [root@gitlab git_data]# git log -1 commit 7015bc7b316cc95e2dfe6c53e06e3900b2edf427 Author: oldboy <admin@oldboyedu.com> Date: Wed Nov 29 19:30:57 2017 +0800 123 合并代码 [root@gitlab git_data]# git merge linux 更新 7015bc7..5a6c037 Fast-forward README | 1 + 1 file changed, 1 insertion(+) [root@gitlab git_data]# git status # 位于分支 master 无文件要提交,干净的工作区 [root@gitlab git_data]# cat README 2017年11月30日 2.合并失败解决 模拟冲突,在文件的同一行做不同修改 在master 分支进行修改 [root@gitlab git_data]# cat README 2017年11月30日 [root@gitlab git_data]# echo "oldboy in master">> README [root@gitlab git_data]# git commit -a -m "oldboy 2017年11月30日 09点20分 " [master 7ab71d4] oldboy 2017年11月30日 09点20分 1 file changed, 1 insertion(+) 切换到linux分支 [root@gitlab git_data]# git checkout linux 切换到分支 'linux' [root@gitlab git_data]# cat README 2017年11月30日 [root@gitlab git_data]# echo "oldboy in linux" >> README [root@gitlab git_data]# git commit -a -m "2017年11月30日 03" [linux 20f1a13] 2017年11月30日 03 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 2017年11月30日 oldboy in master oldboy in linux # 手工解决冲突 [root@gitlab git_data]# git commit -a -m "2017年11月30日 03" [master b6a097f] 2017年11月30日 03 3.删除分支 因为之前已经合并了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 选项强制删除它。
看完本文有收获?那就分享给更多朋友吧~ ---------------------------------------------------------------------------------------------------------------------- 我们尊重原创,也注重分享,文章来源于微信公众号:老男孩Linux,建议关注公众号查看原文。如若侵权请联系qter@qter.org。 ---------------------------------------------------------------------------------------------------------------------- |