GIT分布式版本控制

时间:2022-06-01 16:35:07


一、Git环境准备

[root@linux-node1 ~]# cat /etc/redhat-release   #查看系统版本

CentOS Linux release 7.3.1611 (Core)

[root@linux-node1 ~]# uname -r   #查看内核版本

3.10.0-514.10.2.el7.x86_64

[root@linux-node1 ~]# getenforce   #确认Selinux关闭状态

Disabled

[root@linux-node1 ~]# systemctl stop firewalld #关闭防火墙

 

二、Git安装部署

Git是分布式的版本控制系统,我们只要有了一个原始Git版本仓库,就可以让其他主机克隆走这个原始版本仓库,从而使得一个Git版本仓库可以被同时分布到不同的主机之上,并且每台主机的版本库都是一样的,没有主次之分,极大的保证了数据安全性,并使得用户能够自主选择向那个Git服务器推送文件了,其实部署一个git服务器是非常简单的。

[root@linux-node1 ~]# yum install git git-all

#安装Git

[root@linux-node1 ~]# git config –-global user.name"tom" 

#配置git使用用户

[root@linux-node1 ~]# git config –-global user.email"123456@mail.com" 

#配置git使用邮箱

[root@linux-node1 ~]# git config –-global color.ui=true

[root@linux-node1 ~]# git config –-list

user.name=tom

User.email=123456@mail.com

color.ui=true

三、Git常用命令

add #添加文件内容至索引

bisect #通过二分查找定位引入 bug 的变更

branch #列出、创建或删除分支

checkout #检出一个分支或路径到工作区

clone #克隆一个版本库到一个新目录

commit #记录变更到版本库

diff #显示提交之间、提交和工作区之间等的差异

fetch #从另外一个版本库下载对象和引用

grep #输出和模式匹配的行

init #创建一个空的 Git 版本库或重新初始化一个已存在的版本库

log #显示提交日志

merge #合并两个或更多开发历史

mv #移动或重命名一个文件、目录或符号链接

pull #获取并合并另外的版本库或一个本地分支

push #更新远程引用和相关的对象

rebase #本地提交转移至更新后的上游分支中

reset #重置当前HEAD到指定状态

rm #从工作区和索引中删除文件

show #显示各种类型的对象

status #显示工作区状态

tag #创建、列出、删除或校验一个GPG签名的 tag 对象

 

四、Git基本操作

1、Git提交数据

我们可以简单的把工作目录理解成是一个被Git服务程序管理的目录,Git会时刻的追踪目录内文件的改动,另外在安装好了Git服务程序后,默认就会创建好了一个叫做master的分支,我们直接可以提交数据到了

[root@linux-node1 ~]# mkdirtom 

#创建本地工作目录

[root@linux-node1 ~]# cdtom/ 

#进入本地工作目录

[root@linux-node1 tom]# git init #初始git工作目录

Initialized empty Git repository in /root/tom/.git/

[root@linux-node1 tom]# touch readme.txt

#创建文件

[root@linux-node1 tom]# git status 

#查看git状态

# On branch master

#

# Initial commit

#

# Untracked files:

#   (use "git add <file>..." to include in what will be committed)

#

#readme.txt

nothing added to commit but untracked files present (use "git add" to track)

 

[root@linux-node1 tom]# git add readme.txt 

#git添加文件至暂存区

[root@linux-node1 tom]# git status #次查看状态

# On branch master

#

# Initial commit

#

# Changes to be committed:

#   (use "git rm --cached <file>..." to unstage)

#

#new file:   readme.txt

#

[root@linux-node1 tom]# git commit -m "the first commit" #git cmmit提交暂存取文件至git版本仓库

[master (root-commit) b1ccad5] the first commit

 Committer: root <root@linux-node3.example.com>

Your name and email address were configured automatically based

on your username and hostname. Please check that they are accurate.

You can suppress this message by setting them explicitly:

 

    git config --global user.name "Your Name"

    git config --global user.email you@example.com

 

After doing this, you may fix the identity used for this commit with:

 

    git commit --amend --reset-author

 

 1 file changed, 0 insertions(+), 0 deletions(-)

 create mode 100644 readme.txt

 

2、Git移除数据

有些时候会向把已经添加到暂存区的文件移除,但仍然希望文件在工作目录中不丢失,换句话说,就是把文件从追踪清单中删除。

[root@linux-node1 tom]# touchtest 

#建立文件

[root@linux-node1 tom]# git add test 

#添加文件至暂存区

[root@linux-node1 tom]# git status #查看当前git状态

# On branch master

# Changes to be committed:

#   (use "git reset HEAD <file>..." to unstage)

#

#new file:   test

#

[root@linux-node1 tom]# git rm --cachedtest   #将文件从git暂存区域的追踪列表移除(并不会删除当前工作目录内的数据文件)

rm ‘test

[root@linux-node1 tom]# git status #此时文件已经是未追踪状态了

# On branch master

# Untracked files:

#   (use "git add <file>..." to include in what will be committed)

#

#test

nothing added to commit but untracked files present (use "git add" to track)

#如果想将文件数据从git暂存区和工作目录一起删除,可以做如下操作。

[root@linux-node1 tom]# git add test

再将database文件提交到git暂存区

[root@linux-node1 tom]# git rm -f test #但如果在删除之前数据文件已经被放入到暂存区域的话,git会担心你误删未提交的文件而报错信息,此时可追加强制删除-f参数。

rm ‘test

[root@linux-node1 tom]# ls #查看工作区也没test文件

readme.txt

[root@linux-node1 tom]# git status #查看当前状态

# On branch master

nothing to commit,working directory clean

 

3、Git移动数据

[root@linux-node1 tom]# git mv readme.txt test.txt #git如果要修改文件名称,则使用git mv命令

[root@linux-node1 tom]# git status 

#查看状态发现下次提交会有一个改名操作

# On branch master

# Changes to be committed:

#   (use "git reset HEAD <file>..." to unstage)

#

#renamed:    readme.txt -> test.txt

#

[root@linux-node1 tom]# git commit -m "changed name"  #提交到git版本仓库

[master a8df4cf] change name

 Committer: root <root@linux-node3.example.com>

Your name and email address were configured automatically based

on your username and hostname. Please check that they are accurate.

You can suppress this message by setting them explicitly:

 

    git config --global user.name "Your Name"

    git config --global user.email you@example.com

 

After doing this, you may fix the identity used for this commit with:

 

    git commit --amend --reset-author

 

 1 file changed, 0 insertions(+), 0 deletions(-)

 rename readme.txt => test.txt (100%)

 

#其实可以如下方法改名

[root@linux-node1 tom]# mv test.txt readme.txt #先修改名称

[root@linux-node1 tom]# git rm test.txt #然后删除git版本仓库内的文件快照

rm ‘test.txt’

[root@linux-node1 tom]# git add readme.txt #最后再将新的文件添加进入

[root@linux-node1 tom]# git commit -m "changed the file name" #提交至git版本仓库

[master f585847] changed the file name

 Committer: root <root@linux-node3.example.com>

Your name and email address were configured automatically based

on your username and hostname. Please check that they are accurate.

You can suppress this message by setting them explicitly:

 

    git config --global user.name "Your Name"

    git config --global user.email you@example.com

 

After doing this, you may fix the identity used for this commit with:

 

    git commit --amend --reset-author

 

 1 file changed, 0 insertions(+), 0 deletions(-)

 create mode 100644 readme.txt

 

4、Git历史记录

[root@linux-node1 tom]# git log #查看提交历史记录

commit f585847ebe968dde864e257399ff9fd2d3b7fc7f

Author: root <root@linux-node3.example.com>

Date:   Wed Mar 29 19:44:23 2017 +0800

 

    changed the file name

 

commit a8df4cf95adfca21f54afa0db2c1db78fdbb21d8

Author: root <root@linux-node3.example.com>

Date:   Wed Mar 29 19:40:34 2017 +0800

 

    change name

 

commit b1ccad51afe0c2272e895c16aadf0df842eb88b1

Author: root <root@linux-node3.example.com>

Date:   Wed Mar 29 19:31:17 2017 +0800

 

    the first commit

 

[root@linux-node1 tom]# git log -2 #查看最近几条记录

commit f585847ebe968dde864e257399ff9fd2d3b7fc7f

Author: root <root@linux-node3.example.com>

Date:   Wed Mar 29 19:44:23 2017 +0800

 

    changed the file name

 

commit a8df4cf95adfca21f54afa0db2c1db78fdbb21d8

Author: root <root@linux-node3.example.com>

Date:   Wed Mar 29 19:40:34 2017 +0800

 

change name

 

[root@linux-node1 tom]# git log -p -1 #-p显示每次提交的内容差异,例如仅查看最近一次差异

commit f585847ebe968dde864e257399ff9fd2d3b7fc7f

Author: root <root@linux-node3.example.com>

Date:   Wed Mar 29 19:44:23 2017 +0800

 

    changed the file name

 

diff --git a/readme.txt b/readme.txt

new file mode 100644

index 0000000..e69de29

 

[root@linux-node1 tom]# git log –-stat -2

#–stat简要显示数据增改行数,这样能够看到提交中修改过的内容,对文件添加或移动的行数,并在最后列出所有增减行的概要信息

commit f585847ebe968dde864e257399ff9fd2d3b7fc7f

Author: root <root@linux-node3.example.com>

Date:   Wed Mar 29 19:44:23 2017 +0800

 

    changed the file name

 

 readme.txt | 0

 1 file changed, 0 insertions(+), 0 deletions(-)

 

commit a8df4cf95adfca21f54afa0db2c1db78fdbb21d8

Author: root <root@linux-node3.example.com>

Date:   Wed Mar 29 19:40:34 2017 +0800

 

    change name

 

 readme.txt | 0

 test.txt   | 0

 2 files changed, 0 insertions(+), 0 deletions(-)

 

[root@linux-node1 tom]# git log --pretty=oneline #--pretty根据不同的格式展示提交的历史信息

f585847ebe968dde864e257399ff9fd2d3b7fc7f changed the file name

a8df4cf95adfca21f54afa0db2c1db78fdbb21d8 change name

b1ccad51afe0c2272e895c16aadf0df842eb88b1 the first commit

 

[root@linux-node1 tom]# git log --pretty=fuller -2 #以更详细的模式输出提交的历史记录

commit f585847ebe968dde864e257399ff9fd2d3b7fc7f

Author:     root <root@linux-node3.example.com>

AuthorDate: Wed Mar 29 19:44:23 2017 +0800

Commit:     root <root@linux-node3.example.com>

CommitDate: Wed Mar 29 19:44:23 2017 +0800

 

    changed the file name

 

commit a8df4cf95adfca21f54afa0db2c1db78fdbb21d8

Author:     root <root@linux-node3.example.com>

AuthorDate: Wed Mar 29 19:40:34 2017 +0800

Commit:     root <root@linux-node3.example.com>

CommitDate: Wed Mar 29 19:40:34 2017 +0800

 

    change name

 

还可以使用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@linux-node1 tom]# git log --pretty=format:"%h %cn"      #查看当前所有提交记录的简短SHA-1哈希字串与提交着的姓名

f585847 root

a8df4cf root

b1ccad5 root

 

5、Git还原数据

[root@linux-node1 tom]# echo"Git is a version control system" >> readme.txt

#追加一段话

[root@linux-node1 tom]# git add readme.txt #添加至暂存区

[root@linux-node1 tom]# git commit -m "introduction software" #提交至git版本仓库

[master a391c78] introduce software

 Committer: root <root@linux-node3.example.com>

Your name and email address were configured automatically based

on your username and hostname. Please check that they are accurate.

You can suppress this message by setting them explicitly:

 

    git config --global user.name "Your Name"

    git config --global user.email you@example.com

 

After doing this, you may fix the identity used for this commit with:

 

    git commit --amend --reset-author

 

 1 file changed, 1 insertion(+)

 

此时觉得写得不妥,想还原某一次提交的文件快照

[root@linux-node1 tom]# git log --pretty=oneline #提交的历史信息

a391c78c74bf643e42c6f6e587eea453db05010e introduce software

f585847ebe968dde864e257399ff9fd2d3b7fc7f changed the file name

a8df4cf95adfca21f54afa0db2c1db78fdbb21d8 change name

b1ccad51afe0c2272e895c16aadf0df842eb88b1 the first commit

Git服务程序中有一个叫做HEAD的版本指针,当用户申请还原数据时,其实就是将HEAD指针指向到某个特定的提交版本,但是因为Git是分布式版本控制系统,为了避免历史记录冲突,故使用了SHA-1计算出十六进制的哈希字串来区分每个提交版本,另外默认的HEAD版本指针会指向到最近的一次提交版本记录,而上一个提交版本会叫HEAD^,上上一个版本则会叫做HEAD^^,当然一般会用HEAD~5来表示往上数第五个提交版本。

 

[root@linux-node1 tom]# git reset --hard HEAD^    #还原历史提交版本上一次

HEAD is now at f585847 changed the file name

[root@linux-node1 tom]# cat readme.txt    #查看文件内容(已经还原)

 

刚刚的操作实际上就是改变了一下HEAD版本指针的位置,就是你将HEAD指针放在那里,那么你的当前工作版本就会定位在那里,要想把内容再还原到最新提交的版本,先看查看下提交版本号

[root@linux-node1 tom]# git log --pretty=oneline

f585847ebe968dde864e257399ff9fd2d3b7fc7f changed the file name

a8df4cf95adfca21f54afa0db2c1db78fdbb21d8 change name

b1ccad51afe0c2272e895c16aadf0df842eb88b1 the first commit

 

怎么搞得?竟然没有了Introduction software这个提交版本记录?

原因很简单,因为我们当前的工作版本是历史的一个提交点,这个历史提交点还没有发生过Introduction software更新记录,所以当然就看不到了,要是想"还原到未来"的历史更新点,可以用git reflog命令来查看所有的历史记录:

[root@linux-node1 tom]# git reflog   #查看未来历史更新点

f585847 HEAD@{0}: reset: moving to HEAD^

a391c78 HEAD@{1}: commit: introduce software

f585847 HEAD@{2}: commit: changed the file name

a8df4cf HEAD@{3}: commit: change name

b1ccad5 HEAD@{4}: commit (initial): the first commit

 

[root@linux-node1 tom]# git reset --harda391c78 #找到历史还原点的SHA-1值后,就可以还原(值不写全,系统会自动匹配)

HEAD is now at a391c78 introduction software

 

[root@linux-node1 tom]# cat readme.txt #查看文件内容(已经还原)

Git is a version control system

如是只是想把某个文件内容还原,就不必这么麻烦,直接用git checkout命令就可以的,先写一段话

 

[root@linux-node1 tom]# echo"Some mistkes words" >> readme.txt

[root@linux-node1 tom]# cat readme.txt #查看内容

Git is a version control system

Some mistkes words

我们突然发现不应该写一句话的,可以手工删除(当内容比较多的时候会很麻烦),还可以将文件内容从暂存区中恢复

[root@linux-node1 tom]# git checkout readme.txt

[root@linux-node1 tom]# cat readme.txt 

Git is a version control system

这其中是有一套规则,如果暂存区中有该文件,则直接从暂存区恢复,如果暂存区没有该文件,则将还原成最近一次文件提交时的快照。

 

6、Git管理分支结构

    分支即是平行空间,假设你在为某个手机系统研发拍照功能,代码已经完成了80%,但如果将这不完整的代码直接提交到git仓库中,又有可能影响到其他人的工作,此时我们便可以在该软件的项目之上创建一个名叫"拍照功能"的分支,这种分支只会属于你自己,而其他人看不到,等代码编写完成后再与原来的项目主分支合并下即可,这样即能保证代码不丢失,又不影响其他人的工作。

    一般在实际的项目开发中,我们要尽量保证master分支是非常稳定的,仅用于发布新版本,平时不要随便直接修改里面的数据文件,而工作的时候则可以新建不同的工作分支,等到工作完成后在合并到master分支上面,所以团队的合作分支看起来会像上面图那样。

 

7、Git创建分支

[root@linux-node1 tom]# git branch linux

#创建分支

[root@linux-node1 tom]# git checkout linux     #切换分支

Switched to branch ‘linux’

[root@linux-node1 tom]# git branch       #查看当前分支情况,当前分支前有*

* linux

master

[root@linux-node1 tom]# echo"Create new branch is linux" >> readme.txt

#我们对文件追加一行字符串

[root@linux-node1 tom]# git add readme.txt #提交到暂存区

[root@linux-node1 tom]# git commit -m "new branch" 

#提交到git版本仓库

[linux 8bf5757] new branch

1 file changed, 1 insertion(+)

[root@linux-node1 tom]# git checkout master #我们在提交文件后再切回master分支

Switched to branch ‘master’

[root@linux-node1 tom]# cat readme.txt #查看文件内容,发现并没有新追加的字符串

Git is a version control system

 

8、Git合并分支

现在,我们想把linux的工作成果合并到master分支上了,则可以使用"git merge"命令来将指定的的分支与当前分支合并

[root@linux-node1 tom]# git branch 

#查看是否在master分支

linux

* master

[root@linux-node1 tom]# git merge linux #合并Linux分支至master

Updating a391c78..280077b

Fast-forward

readme.txt | 1 +

1 file changed, 1 insertion(+)

[root@linux-node1 tom]# cat readme.txt #查看合并后的readme文件

Git is a version control system

Create new branch is linux

[root@linux-node1 tom]# git branch -d linux   #确认合并完成后,可以放心地删除Linux分支

Deleted branch linux (was 280077b).

[root@linux-node1 tom]# git branch #删除后,查看branch,只剩下master分支了

* master

 

9、Git分支冲突

[root@linux-node1 tom]# git checkout -b linux 

#创建分支并切换到该分支

[root@linux-node1 tom]# git branch #查看分支

* linux

master

[root@linux-node1 tom]# vim readme.txt #编辑readme文件

[root@linux-node1 tom]# git add readme.txt 

#Linux分支添加readme至暂存区

[root@linux-node1 tom]# git commit -m "create two" #Linux分支提交readme

# On branch linux

# Untracked files:

#   (use "git add <file>..." to include in what will be committed)

#

#.readme.txt.swp

nothing added to commit but untracked files present (use "git add" to track)

[root@linux-node1 tom]# git checkout master             #切换到master分支

Switched to branch ‘master’

[root@linux-node1 tom]# git branch    #查看是否切换至master分支

linux

* master

[root@linux-node1 tom]# vim readme.txt #编在master分支上修改readme文件同一行的内容

[root@linux-node1 tom]# git add readme.txt

#添加至暂存区

[root@linux-node1 tom]# git commit -m ‘create two master’   #提交至Git版本仓库

# On branch master

# Untracked files:

#   (use "git add <file>..." to include in what will be committed)

#

#.readme.txt.swp

nothing added to commit but untracked files present (use "git add" to track)

[root@linux-node1 tom]# git merge linux     #合并Linux分支(冲突)

Auto-merging readme.txt

CONFLICT (content): Merge conflict in readme.txt

Automatic merge failed; fix conflicts and then commit the result.

#那么此时,我们在masterlinux分支上都分别对中readme文件进行了修改并提交了,那这种情况下Git就没法再为我们自动的快速合并了,它只能告诉我们readme文件的内容有冲突,需要手工处理冲突的内容后才能继续合并

[root@linux-node1 tom]# cat readme.txt #冲突内容如下

#Git< <<<<<<=======>>>>>>>分割开了各个分支冲突的内容,我们需要手工的删除这些符号,并将内容修改

1 hehe

<<<<<<< HEAD

=======

>>>>>>> linux

Create new branch is linux

[root@linux-node1 tom]# git add readme.txt #再次添加至暂存区

[root@linux-node1 tom]# git commit -m ‘config’ #提交至git版本仓库

[master eb9bb83] config

[root@linux-node1 tom]# git branch -d linux #最后删除Linux分支结束

Deleted branch linux (was 13a42ad).

[root@linux-node1 tom]# git branch #检查是否删除完毕

* master

 

10、Git管理标签

当版本仓库内的数据有个大的改善或者功能更新,我们经常会打一个类似于软件版本号的标签,这样通过标签就可以将版本库中的某个历史版本给记录下来,方便我们随时将特定历史时期的数据取出来用,另外打标签其实只是像某个历史版本做了一个指针,所以一般都是瞬间完成的。

[root@linux-node1 ~]# cdtom/ #进入git版本控制系统

[root@linux-node1 tom]# git tag v1.0 #当前提交内容打一个标签(方便快速回滚)

[root@linux-node1 tom]# git tag #查看当前所有的标签

v1.0

[root@linux-node1 tom]# git show v1.0 #查看当前1.0版本的详细信息

commit 280077b1606bd5b411e81ab3a19752eaa708dd1e

Author: root <root@linux-node3.example.com>

Date:   Wed Mar 29 21:09:11 2017 +0800

 

    new branch

 

diff --git a/readme.txt b/readme.txt

index 8f6e0fc..e252291 100644

--- a/readme.txt

+++ b/readme.txt

@@ -1 +1,2 @@

 Git is a version control system

+Create new branch is linux

[root@linux-node1 tom]# git tag v1.2 -m "version 1.2 release is test" #创建带有说明的标签,-a指定标签名字,-m指定说明文字

[root@linux-node1 tom]# git tag -d v1.0  #我们为同一个提交版本设置了两次标签,删除之前的v1.0

Deleted tag ‘v1.0’ (was 280077b)

[root@linux-node1 tom]# git tag   #再次查看,v1.0已经被删除

v1.2