一 。git工作流程
Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目,Git 与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持。GIT不仅仅是个版本控制系统,它也是个内容管理系统(CMS),工作管理系统等。
如果你是一个具有使用SVN背景的人,你需要做一定的思想转换,来适应GIT提供的一些概念和特征。
Git 与 SVN 区别点:
1、GIT是分布式的,SVN不是:这是GIT和其它非分布式的版本控制系统,例如SVN,CVS等,最核心的区别。
2、GIT把内容按元数据方式存储,而SVN是按文件:所有的资源控制系统都是把文件的元信息隐藏在一个类似.svn,.cvs等的文件夹里。
3、GIT分支和SVN的分支不同:分支在SVN中一点不特别,就是版本库中的另外的一个目录。
4、GIT没有一个全局的版本号,而SVN有:目前为止这是跟SVN相比GIT缺少的最大的一个特征。
5、GIT的内容完整性要优于SVN:GIT的内容存储使用的是SHA-1哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏。
git 工作区 暂存区 版本库概念:
》工作区:就是你在电脑里能看到的目录。
》暂存区:英文叫stage, 或index。一般存放在 ".git目录下" 下的index文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。
》版本库:工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。
比如我新建了一个项目 该项目就是工作区 可以在该项目下创建一个git版本库 编辑的源代码默认都是存在于工作区 工作区可以通过git add 添加代码到暂存区 暂存区的代码可以提交到最终版本库
使用eclipse 其中新建的项目webtest默认是在工作区 其中git视图中的 staged changes 就是讲文件加入到暂存取 工作区有文件修改后 unstaged changes 出现该文件等待你加入暂存取 可以将暂存区的数据 commit到版本库中
图解(来自runoobj)
演示eclipse下的工作区 暂存区和版本库
二。 git本地安装
官网 (https://git-scm.com/book/zh/v1)
环境:Centos环境
Yum -y isntall git-core
查看git版本
Git --version
查看git帮助
[root@node3 bin]# git --help
usage: git [--version] [--help] [-c name=value]
[--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
[-p|--paginate|--no-pager] [--no-replace-objects] [--bare]
[--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
<command> [<args>]
The most commonly used git commands are:
add Add file contents to the index
bisect Find by binary search the change that introduced a bug
branch List, create, or delete branches
checkout Checkout a branch or paths to the working tree
clone Clone a repository into a new directory
commit Record changes to the repository
diff Show changes between commits, commit and working tree, etc
fetch Download objects and refs from another repository
grep Print lines matching a pattern
init Create an empty Git repository or reinitialize an existing one
log Show commit logs
merge Join two or more development histories together
mv Move or rename a file, a directory, or a symlink
pull Fetch from and merge with another repository or a local branch
push Update remote refs along with associated objects
rebase Forward-port local commits to the updated upstream head
reset Reset current HEAD to the specified state
rm Remove files from the working tree and from the index
show Show various types of objects
status Show the working tree status
tag Create, list, delete or verify a tag object signed with GPG
三。 git常用基本命令
一般git管理本地有个完整的工作区,暂存区和版本库 所以基本基于本机操作
git常用基本命令如下
1。git创建仓库
任意目录 git init [目录名 不指定当前目录生成.git指定就在指定目录创建.git]当前目录创建一个隐藏目录.git
[root@node3 myproject]# git init
Initialized empty Git repository in /root/git/myproject/.git/
[root@node3 myproject]# ll
total 0
[root@node3 myproject]# ls -a
. .. .git
[root@node3 myproject]# cd .git
[root@node3 .git]# ll
total 16
drwxr-xr-x 2 root root 6 Nov 3 02:36 branches
-rw-r--r-- 1 root root 92 Nov 3 02:36 config
-rw-r--r-- 1 root root 73 Nov 3 02:36 description
-rw-r--r-- 1 root root 23 Nov 3 02:36 HEAD
drwxr-xr-x 2 root root 4096 Nov 3 02:36 hooks
drwxr-xr-x 2 root root 20 Nov 3 02:36 info
drwxr-xr-x 4 root root 28 Nov 3 02:36 objects
drwxr-xr-x 4 root root 29 Nov 3 02:36 refs
2。git配置(git config)
Git配置决定了git仓库的行为 配置的参数以键值对存储 具体参数 参考官网(https://git-scm.com/docs/git-config) 默认的git配置有三种
1》系统配置 /etc/gitconfig系统中所有用户都公用的全局配置 如果用户和当前仓库都没有某个参数时 系统配置文件中的参数就生效 git -config --system键“值”
2》全局配置 ~/.gitconfig 当前登录用户的全局配置 在当前用户的工作目录下 当前用户创建了多个仓库 没有某个参数时 全局配置生效git -config --global键“值”
3》当前仓库 仓库/.git/config文件里 就近原则 这里没有 找全局 全局没有找系统
git -config --local 键 “值” (以下测试是git init需要先创建一个空仓库 有.git文件夹)
测试例子
[root@node3 .git]# git config --system user.name "jiaozi" 系统中设置用户名jiaozi
[root@node3 .git]# git config --global user.name "jiaozi1" 全局中设置用户名 jiaozi1
[root@node3 .git]# git config --local user.name "jiaozi2" 本地仓库设置用户名 jiaozi2
[root@node3 .git]# git config --get user.name 当前仓库.git目录中获取 是jiaozi2
jiaozi2
[root@node3 .git]# git config --system --get user.name 通过指定 --system取系统
jiaozi
[root@node3 .git]# git config --global --get user.name
jiaozi1
[root@node3 .git]# cd .. 到达.git上一级目录也就是仓库根目录 也是jiaozi2
[root@node3 myproject]# git config --get user.name
jiaozi2
[root@node3 myproject]# cd .. 去到别的目录 获取的是用户 切换成其他用户是jiaozi
[root@node3 git]# git config --get user.name
jiaozi1
查看具体的文件
[root@node3 .git]# more config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[user]
name = jiaozi2
[root@node3 .git]# more ~/.gitconfig
[user]
name = jiaozi1
[root@node3 .git]# more /etc/gitconfig
[user]
name = jiaozi
如果登录过一次系统记录了用户名密码后,想再次输入可以使用命令(--local --global也重置)
git config --system --unset credential.helper
3。git添加文件到暂存区(git add)
git仓库也是使用类文件系统这样的目录结构管理文件 所以工作区文件使用git add命令后 该文件被加入objects的对象库中index目录树也及时暂存区 会添加一个引用到该对象表示只是 暂存(图片引用自菜鸟教程)
举例:
[root@node3 myproject]# echo hello>a.txt
[root@node3 myproject]# ll
total 4
-rw-r--r-- 1 root root 6 Nov 3 03:19 a.txt
[root@node3 myproject]# git add a.txt
[root@node3 myproject]# 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
│ ├── ce
│ │ └── 013625030ba8dba906f756967f9e9ca394464a
│ ├── info
│ └── pack
└── refs
├── heads
└── tags
10 directories, 15 files
objects目录每个文件都会生成一个2位随机字符串的目录 和该目录下 随机字符串的二进制文件 该文件是个压缩文件 可以通过
git cat-file -p 2位目录+32位目录 查看内容
在添加一个试试
[root@node3 myproject]# echo test>b.txt
[root@node3 myproject]# git add b.txt
[root@node3 myproject]# 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
│ ├── 9d
│ │ └── aeafb9864cf43055ae93beb0afd6c7d144bfa4
│ ├── ce
│ │ └── 013625030ba8dba906f756967f9e9ca394464a
│ ├── info
│ └── pack
└── refs
├── heads
└── tags
11 directories, 16 files
查看内容
[root@node3 myproject]# git cat-file -p 9daeafb9864cf43055ae93beb0afd6c7d144bfa4
test
[root@node3 myproject]# git cat-file -p ce013625030ba8dba906f756967f9e9ca394464a
Hello
4。git暂存区添加到版本库(git commit 文件名 -m “注释”)
实例演示
[root@node3 myproject]# ll
total 8
-rw-r--r-- 1 root root 11 Nov 3 04:03 a.txt
-rw-r--r-- 1 root root 7 Nov 3 03:58 b.txt
[root@node3 myproject]# git status -s
?? a.txt ??表示未添加到暂存区
?? b.txt
[root@node3 myproject]# git add a.txt
[root@node3 myproject]# git status -s
A a.txt A表示添加到暂存区
?? b.txt
[root@node3 myproject]# git commit a.txt -m "a" 如果需要提交必须先设置用户名和邮箱
*** 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@node3.(none)')
[root@node3 myproject]# git config --global user.email "you@example.com"
[root@node3 myproject]# git commit a.txt -m "a"
[master (root-commit) 930c52d] a
1 file changed, 2 insertions(+)
create mode 100644 a.txt
[root@node3 myproject]# git status -s 提交后status中看不到a.txt了
?? b.txt
5。Git比较文件修改(git diff文件名 )
Git可以查看工作区的文件修改和暂存区的文件变化
root@node3 myproject]# more b.txt
tttttt
[root@node3 myproject]# git add b.txt
修改文件 添加一行 1234
[root@node3 myproject]# git status -s
AM b.txt
[root@node3 myproject]# git diff 查看工作区文件和暂存区文件不一致
diff --git a/b.txt b/b.txt
index 33262c0..dfd0efb 100644
--- a/b.txt
+++ b/b.txt
@@ -1 +1,2 @@
tttttt
+1234 添加了1234
[root@node3 myproject]# git diff --cached
diff --git a/b.txt b/b.txt
new file mode 100644
index 0000000..33262c0
--- /dev/null
+++ b/b.txt
@@ -0,0 +1 @@
+tttttt
6。Git暂存区移除(git rm --cached 文件名 )
[root@node3 myproject]# echo dd>c.txt
[root@node3 myproject]# git status -s
D b.txt
?? b.txt
?? c.txt
[root@node3 myproject]# git add c.txt
[root@node3 myproject]# git status -s
D b.txt
A c.txt
?? b.txt
[root@node3 myproject]# git rm --cached c.txt
rm 'c.txt'
[root@node3 myproject]# git status -s
D b.txt
?? b.txt
?? c.txt
7。Git重置(git reset |revert版本库 )
所有commit其实是一个日志可以通过git log查看
D:\workflow>git log
commit 6945d82b9e2a8fd8da8ee4b4aba7df0a3b187ce1 (HEAD -> master)
Author: lixin1112003@126.com <lixin1112003@126.com>
Date: Thu Apr 18 21:58:12 2019 +0800
b
commit 4fcbdd1c13810fdd6f3a19ecee97ba1dd1a7cd14
Author: lixin1112003@126.com <lixin1112003@126.com>
Date: Thu Apr 18 21:52:24 2019 +0800
a
HEAD指针其实(查看.git\refs\heads\master文件其实就是git log中最近一条提交的id值 6945d82b9e2a8fd8da8ee4b4aba7df0a3b187ce1)
此处比较git reset和git revert区别
如下比如做了两次提交:
第一次:echo a>a.txt && git add a.txt && git commit -m a
第二次:echo b>b.txt && git add b.txt && git commit -m b
1. 使用git reset logid作用其实是将提交历史回滚到logid位置,之前的代码都进入暂存区
模拟重置到a对应的logid
D:\workflow>git reset 4fcbdd1c13810fdd6f3a19ecee97ba1dd1a7cd14
D:\workflow>git status -s
?? b.txt
D:\workflow>dir
驱动器 D 中的卷是 软件
卷的序列号是 0008-156A
D:\workflow 的目录
2019-04-18 21:53 <DIR> .
2019-04-18 21:53 <DIR> ..
2019-04-18 21:52 3 a.txt
2019-04-18 21:53 3 b.txt
2 个文件 6 字节
2 个目录 110,943,375,360 可用字节
a之后提交的b版本的文件都进入了工作区,如果是新增是?? 如果是删除是D
查看git log 发现b之前日志也清除掉了
D:\workflow>git log
commit 4fcbdd1c13810fdd6f3a19ecee97ba1dd1a7cd14 (HEAD -> master)
Author: lixin1112003@126.com <lixin1112003@126.com>
Date: Thu Apr 18 21:52:24 2019 +0800
a
git reset有两种模式:soft和hard模式,soft(默认)和hard
hard强制将当前的log版本覆盖本地,并同步。HEAD指向revert当前的logid
比如使用git reset --hard
D:\workflow>git reset --hard 4fcbdd1c13810fdd6f3a19ecee97ba1dd1a7cd14
HEAD is now at 4fcbdd1 a
D:\workflow>git status -s
D:\workflow>dir
驱动器 D 中的卷是 软件
卷的序列号是 0008-156A
D:\workflow 的目录
2019-04-18 22:16 <DIR> .
2019-04-18 22:16 <DIR> ..
2019-04-18 21:52 3 a.txt
1 个文件 3 字节
2 个目录 110,942,846,976 可用字节
注意git reset一旦重置 ,之前的日志都删除并且都丢失了。
如果本地分支和远程分支出现冲突,使用远程分支覆盖本地分支
使用 git reset --merge
2. 使用git revert logid作用其实是将lgoid位置及以前都撤销掉(之前是新增文件,反向就是删除,之前日志是删除,反向就是新增),覆盖本地,并产生一个新的提交日志,旧日志还存在。
下面例子revert掉b,实际上b.txt就删除掉了,多了一个revert日志。
git revert 0c46649332a25e6c2e2cf98b33f9cbac0deb5a85
D:\workflow>dir
驱动器 D 中的卷是 软件
卷的序列号是 0008-156A
D:\workflow 的目录
2019-04-18 22:21 <DIR> .
2019-04-18 22:21 <DIR> ..
2019-04-18 21:52 3 a.txt
1 个文件 3 字节
2 个目录 110,942,846,976 可用字节
D:\workflow>git log
commit 1f4e6d6b76965b771cceb674176ddc57411c2a86 (HEAD -> master)
Author: lixin1112003@126.com <lixin1112003@126.com>
Date: Thu Apr 18 22:21:30 2019 +0800
Revert "b"
This reverts commit 0c46649332a25e6c2e2cf98b33f9cbac0deb5a85.
commit 0c46649332a25e6c2e2cf98b33f9cbac0deb5a85
Author: lixin1112003@126.com <lixin1112003@126.com>
Date: Thu Apr 18 22:20:39 2019 +0800
b
commit 4fcbdd1c13810fdd6f3a19ecee97ba1dd1a7cd14
Author: lixin1112003@126.com <lixin1112003@126.com>
Date: Thu Apr 18 21:52:24 2019 +0800
a
既然之前b日志还在就可以重置回去
D:\workflow>git reset --hard 0c46649332a25e6c2e2cf98b33f9cbac0deb5a85
HEAD is now at 0c46649 b
D:\workflow>dir
驱动器 D 中的卷是 软件
卷的序列号是 0008-156A
D:\workflow 的目录
2019-04-18 22:25 <DIR> .
2019-04-18 22:25 <DIR> ..
2019-04-18 21:52 3 a.txt
2019-04-18 22:25 3 b.txt
2 个文件 6 字节
2 个目录 110,942,846,976 可用字节
尝试删除一个文件
D:\workflow>del b.txt
D:\workflow>git add b.txt
D:\workflow>git commit -m delb
[master 504d7dd] delb
1 file changed, 1 deletion(-)
delete mode 100644 b.txt
D:\workflow>git log
commit 504d7dd77c7ebc33142251172917280f9106a469 (HEAD -> master)
Author: lixin1112003@126.com <lixin1112003@126.com>
Date: Thu Apr 18 22:29:16 2019 +0800
delb
commit 0c46649332a25e6c2e2cf98b33f9cbac0deb5a85
Author: lixin1112003@126.com <lixin1112003@126.com>
Date: Thu Apr 18 22:20:39 2019 +0800
b
commit 4fcbdd1c13810fdd6f3a19ecee97ba1dd1a7cd14
Author: lixin1112003@126.com <lixin1112003@126.com>
Date: Thu Apr 18 21:52:24 2019 +0800
a
因为本地删除了,尝试revert到HEAD也就是最上面一条日志,发现文件删除了
D:\workflow>dir
驱动器 D 中的卷是 软件
卷的序列号是 0008-156A
D:\workflow 的目录
2019-04-18 22:28 <DIR> .
2019-04-18 22:28 <DIR> ..
2019-04-18 21:52 3 a.txt
1 个文件 3 字节
2 个目录 110,942,846,976 可用字节
D:\workflow>git revert HEAD
D:\workflow>dir
驱动器 D 中的卷是 软件
卷的序列号是 0008-156A
D:\workflow 的目录
2019-04-18 22:30 <DIR> .
2019-04-18 22:30 <DIR> ..
2019-04-18 21:52 3 a.txt
2019-04-18 22:30 3 b.txt
2 个文件 6 字节
2 个目录 110,942,846,976 可用字节
8。Git重命名(git mv旧文件名 新文件名 )
Git添加到暂存区的文件可以重命名为其他文件名 比如
[root@node3 myproject]# git mv b.txt b1.txt
[root@node3 myproject]# git status -s
RM b.txt -> b1.txt
?? c.txt
9。Git查看文件状态|当前分支(git status )
Git status 查看工作区和暂存区的文件的状态
D:\workflow>git status
On branch master 当期master分支
-s 是指定简洁输出
文件状态
A 表示 git add 新加入到暂存区的文件
D 表示从暂存区删除
M 表示已经添加到暂存区但是工作区有修改的文件
RM 表示工作区文件被重命名
10。Git查看文件状态(git status )
查看提交日志信息
[root@node3 myproject]# git log
commit e35fe0a7e8511f9e4966025b681f1803f5b090fb
Author: jiaozi1 <you@example.com>
Date: Fri Nov 3 05:15:54 2017 -0700
d.txt
四。 git版本库分支
分支 每个项目都存在一个主线有些功能必须从主线中分支出来而不影响主线同时继续工作 比如 mysql被oracle收购后 分支出mariadb(独立)和oraclemysql(主分支)
分支常用命令:
1。查看所有分支(默认只有master)
[root@node3 myproject]# git branch
* master
2。查看所有分支(默认只有master)
创建分支(该分支被创建 就相当于拷贝了当前分支(默认master)的一份快照 以后修改了 不会影响分支 分支修改不影响主分支)
[root@node3 myproject]# git branch
* master
[root@node3 myproject]# git branch test
[root@node3 myproject]# git branch
* master
* test
3。查看所有分支(默认只有master)
切换分支(切换到哪个分支 提交的代码就提交到哪个分支 默认是master)
[root@node3 myproject]# git branch test 创建分区 test
[root@node3 myproject]# echo 3>c.txt 默认工作区创建一个c.txt
[root@node3 myproject]# git add c.txt 添加到暂存区
[root@node3 myproject]# git commit -m "c.txt" 提交到当前分支master
[master cc8f260] c.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 c.txt
[root@node3 myproject]# ll
total 4
-rw-r--r-- 1 root root 1 Nov 3 05:02 a.txt
-rw-r--r-- 1 root root 0 Nov 3 05:02 b.txt
-rw-r--r-- 1 root root 0 Nov 3 05:03 c.txt
[root@node3 myproject]# git status -s
[root@node3 myproject]# git checkout test 切换到test分支 test是没有创建c.txt之前创建 所有应该没有c.txt
Switched to branch 'test'
[root@node3 myproject]# ll
total 4
-rw-r--r-- 1 root root 1 Nov 3 05:02 a.txt
-rw-r--r-- 1 root root 0 Nov 3 05:02 b.txt
[root@node3 myproject]# git checkout master 切换回master c.txt回来了
Switched to branch 'master'
[root@node3 myproject]# ll
total 4
-rw-r--r-- 1 root root 1 Nov 3 05:02 a.txt
-rw-r--r-- 1 root root 0 Nov 3 05:02 b.txt
-rw-r--r-- 1 root root 0 Nov 3 05:04 c.txt
可以使用 git checkout -b (branchname) 命令来创建新分支并立即切换到该分支下
4。合并分支(当某几个分支有了独立内后 就可以合并到当前分支 分支过程中可能存在冲突 解决过程不列出)
[root@node3 myproject]# git checkout -b test 创建分区并切换
Switched to a new branch 'test'
[root@node3 myproject]# echo 4>d.txt 分支中添加d.txt
[root@node3 myproject]# git add d.txt
[root@node3 myproject]# git commit -m "d.txt" 提交到test当前分区
[test e35fe0a] d.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 d.txt
[root@node3 myproject]# ll 查看分区
total 4
-rw-r--r-- 1 root root 1 Nov 3 05:02 a.txt
-rw-r--r-- 1 root root 0 Nov 3 05:02 b.txt
-rw-r--r-- 1 root root 0 Nov 3 05:04 c.txt
-rw-r--r-- 1 root root 0 Nov 3 05:15 d.txt
[root@node3 myproject]# git checkout master 切换到master 将test合并到当前分支master
Switched to branch 'master'
[root@node3 myproject]# git merge test 合并test 合并到哪个就切换回哪个
Updating cc8f260..e35fe0a
Fast-forward
d.txt | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 d.txt
5。删除分支(删除分支后 不能切换)
[root@node3 myproject]# git branch -d test
Deleted branch test (was 611f3e1).
[root@node3 myproject]# git checkout test
error: pathspec 'test' did not match any file(s) known to git.
五。 git版本库tag
1。当前分支新建tag
git tag -a v1.0 -m 'v1.0new'
不添加注释可以简易安装
D:\workflow>git tag a6d
2。删除tag
D:\workflow>git tag -d v1.0
Deleted tag 'v1.0' (was e454593)
3。切换到tag
D:\workflow>git tag a6d
D:\workflow>git tag
a6d
D:\workflow>git checkout a6d
Note: checking out 'a6d'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b <new-branch-name>
HEAD is now at a6d44bb... Revert "delb"
注意tag切换回处于detached HEAD状态,因为 tag 相当于是一个快照,是不能更改它的代码的,切换到tag历史记录 会使当前指针处在分离头指针状态,这个时候的修改是很危险的,在切换回主线时如果没有合并,之前的修改提交基本都会丢失,如果需要修改可以尝试git checkout -b branch tag创建一个基于指定tag的分支,例如:git checkout -b test v0.1.0 这个时候就在这个test分支上进行开发,之后可以切换到主线合并。
4。提交tag到远程
默认情况下,git push 并不会把标签传送到远端服务器上,
只有通过显式命令才能分享标签到远端仓库。其命令格式如同推送分支,
运行 git push origin [tagname] 即可:
git push origin v1.5
如果要一次推送所有本地新增的标签上去,可以使用 --tags 选项:
git push origin --tags