git使用
1.版本控制
记录若干文件内容变化,以便将来查阅特定版本修订情况,在开发中,必须允许可以很容易对产品的版本进行任意回滚,版本控制工具实现这个功能的原理简单来讲,就是你每修改一次代码,它就帮你做一次快照
版本管理工具发展简史,cvs -->svn --> git 参考http://luckypoem14.github.io/test/2012/04/24/scm-history/
CVS--Concurrent Versions System
此工具是一个开源工具,与后面提到的SVN是同一个厂家:Collab.Net提供的。
CVS是源于unix的版本控制工具,对于CVS的安装和使用最好对unix的系统有所了解能更容易学习,CVS的服务器管理需要进行各种命令行操作。目前,CVS的客户端有winCVS的图形化界面,服务器端也有CVSNT的版本,易用性正在提高。
此工具是相当著名,使用得相当广泛的版本控制工具之一,使用成熟的“Copy-Modify-Merge"开发模型,可以大大的提高开发效率,适合于项目比较大,产品发布频繁,分支活动频繁的中大型项目。
svn全称CollabNet subversion,是一个开源版本控制系统,始于2000年
github,是一个web界面的git管理平台,也就是说它底层的技术驱动依然是git。一句话区分,git是管理工具,github是在线的基于git的平台(或者叫做服务)。github是公开的,谁都可以注册账号,并创建自己的项目,大部分项目以代码为主,比如wordpress、discuz都是托管在github里面的,当然还有好多好多开源的软件。
既然github是一个公共的,在线的提供服务的平台,那企业就可以把公司内部的代码托管在这里,为了安全我们可以选择付费服务,定制个性化方案。但毕竟github在国外,要想获得更好的功能还需要花钱,小企业或者个人用户自然是不愿意去开销了。
还好又一款开源的软件可以帮我们搭建一套类似github的平台,这就是接下来我要介绍的gitlab。 gitlab适合企业内部构建私有代码管理平台,它有健全的权限控制系统和各种强大的功能,很赞。
所以,gitlab和github一样,也是一个基于git的提供web界面的代码管理平台。
gitlab可以认为是一个开源的github,两者没有直接关系。
2. git使用
git安装:yum install –y git.
Linux自带git,查看:
[root@greg02 ~]# git --version git version 1.8.3.1
git init初始化
git add file.py 把代码放入git暂存区
git commit 从代码暂存区存入仓库
[root@greg02 ~]#mkdir /data/gitroot [root@greg02 ~]#cd /data/gitroot/ [root@greg02 gitroot]#ls [root@greg02 gitroot]#git init Initialized empty Git repository in /data/gitroot/.git/ [root@greg02 gitroot]#ls -la total 0 drwxr-xr-x 3 root root 18 Nov 15 23:37 . drwxr-xr-x 7 root root 77 Nov 15 23:37 .. drwxr-xr-x 7 root root 119 Nov 15 23:37 .git [root@greg02 gitroot]#vim first_prog.py [root@greg02 gitroot]#git add first_prog.py [root@greg02 gitroot]#git commit *** Please tell me who you are. Run git config --global user.email "you@example.com" git config --global user.name "Your Name" to set your account's default identity. Omit --global to set the identity only in this repository. fatal: unable to auto-detect email address (got 'root@greg02.(none)') 报错增加邮箱和用户 [root@greg02 gitroot]#git config --global user.email 292409083@qq.com [root@greg02 gitroot]#git config --global user.name Greg Li [root@greg02 gitroot]#git commit 提交后显示文本,添加更改内容 # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # On branch master # # Initial commit # # Changes to be committed: # (use "git rm --cached <file>..." to unstage) # # new file: first_prog.py git test commit wq保存退出显示添加的内容 [master (root-commit) a276887] git test commit 1 files changed, 3 insertions(+) create mode 100644 1.txt create mode 100644 first_prog.py 再次提交 [root@greg02 gitroot]#git commit # On branch master nothing to commit, working directory clean 修改后提交 [root@greg02 gitroot]#vim first_prog.py [root@greg02 gitroot]#git add first_prog.py [root@greg02 gitroot]#git commit 不加内容退出 Aborting commit due to empty commit message. [root@greg02 gitroot]#git commit -m "second commit test" [master 37f52aa] second commit test 1 file changed, 1 insertion(+)
git status 查看当前的代码状态
添加文件先不add,查看状态 [root@greg02 gitroot]#vim readme [root@greg02 gitroot]#git status # On branch master # 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@greg02 gitroot]#git add . [root@greg02 gitroot]#git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: readme
git checkout把代码从暂存区回滚到工作区
[root@greg02 gitroot]#vim second_prog.py [root@greg02 gitroot]#cat first_prog.py def SayHi(): print("Hello") print("third change") print("Test Change 2") [root@greg02 gitroot]#git checkout first_prog.py [root@greg02 gitroot]#cat first_prog.py def SayHi(): print("Hello") print("Test Change 2") [root@greg02 gitroot]#git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: readme # # 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: first_prog.py
git log 在实际工作中,我们不可能记得一个几千行的文件每次都改了什么内容,不然要版本控制系统干什么。版本控制系统肯定有某个命令可以告诉我们历史记录,在Git中,用git log
命令查看:
[root@greg02 gitroot]#git log commit 37f52aa27cab9d89c63f0884c6c634457c80fd21 Author: Greg <292409083@qq.com> Date: Thu Nov 16 00:04:35 2017 +0800 second commit test commit a27688738797fdbe7f884d74846b33357d793ff1 Author: Greg <292409083@qq.com> Date: Wed Nov 15 23:58:44 2017 +0800 git test commit
git log
命令显示从最近到最远的提交日志,我们可以看到4次提交,最近的一次是add new content,上一次是update again,最早的一次是commit my first git file
。 如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline
参数:
[root@greg02 gitroot]#git log --pretty=oneline 37f52aa27cab9d89c63f0884c6c634457c80fd21 second commit test a27688738797fdbe7f884d74846b33357d793ff1 git test commit
一大串数字是commit id
(版本号)是一个SHA1计算出来的一个非常大的数字,用十六进制表示
为什么commit id
需要用这么一大串数字表示呢?因为Git是分布式的版本控制系统,后面我们还要研究多人在同一个版本库里工作,如果大家都用1,2,3……作为版本号,那肯定就冲突了。
回滚
Git必须知道当前版本是哪个版本,在Git中,用HEAD
表示当前版本,也就是最新的提交be02137bb2f54bbef0c2e99202281b3966251952(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,当然往上100个版本写100个^
比较容易数不过来,所以写成HEAD~100
。
git reset --hard HEAD^回滚到上一次
[root@greg02 gitroot]#git log --pretty=oneline 37f52aa27cab9d89c63f0884c6c634457c80fd21 second commit test a27688738797fdbe7f884d74846b33357d793ff1 git test commit [root@greg02 gitroot]#git reset --hard HEAD^ HEAD is now at a276887 git test commit [root@greg02 gitroot]#git log --pretty=oneline a27688738797fdbe7f884d74846b33357d793ff1 git test commit
再回滚回来
git reset --hard 37f52a回滚到指定版本
[root@greg02 gitroot]#git reset --hard 37f52aa27cab9d89c63f0884c6c634457c80fd21 HEAD is now at 37f52aa second commit test [root@greg02 gitroot]#git log --pretty=oneline 37f52aa27cab9d89c63f0884c6c634457c80fd21 second commit test a27688738797fdbe7f884d74846b33357d793ff1 git test commit
当关闭命令行后或者关机后再次启动发现版本号查看不了,又想回滚怎么办
git reflog查看所有版本
[root@greg02 gitroot]#git reflog 37f52aa HEAD@{0}: reset: moving to 37f52aa27cab9d89c63f0884c6c634457c80fd21 a276887 HEAD@{1}: reset: moving to HEAD^ 37f52aa HEAD@{2}: commit: second commit test a276887 HEAD@{3}: commit (initial): git test commit
工作区(Working Directory)
比如/data/gitroot
版本库(Repository)
工作区有一个隐藏目录.git
,这个不算工作区,而是Git的版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master
,以及指向master
的一个指针叫HEAD
。
第一步是用git add
把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit
提交更改,实际上就是把暂存区的所有内容提交到当前分支。
因为我们创建Git版本库时,Git自动为我们创建了唯一一个master
分支,所以,现在,git commit
就是往master
分支上提交更改。
你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。
[root@greg02 gitroot]#git rm 1.txt rm '1.txt' [root@greg02 gitroot]#git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # deleted: 1.txt # [root@greg02 gitroot]#ls first_prog.py [root@greg02 gitroot]#git checkout -- 1.txt error: pathspec '1.txt' did not match any file(s) known to git. [root@greg02 gitroot]#git reset HEAD 1.txt Unstaged changes after reset: D 1.txt [root@greg02 gitroot]#git status # On branch master # 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: 1.txt # no changes added to commit (use "git add" and/or "git commit -a") [root@greg02 gitroot]#git checkout -- 1.txt [root@greg02 gitroot]#ls 1.txt first_prog.py
git checkout
其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。