集中式vs分布式
-
集中式CVS、SVN
- 速度慢,必须联网,开源精神不符
- 版本库集中放在中央服务器,工作时,获取最新版本,工作完成后,再推送给中央服务器!
-
分布式
- 无中央服务器,每个人的电脑都是一个完整的版本库
- 安全性能更高
- 通常有一台充当“中央服务器”的电脑,仅仅作为方便“交换”大家的修改
安装使用
Yum安装:
[root@node1 ~]# yum install git -y
为node1上所有的git仓库设置用户名和Email
[root@node1 ~]# git config --global user.name "Your Name"
[root@node1 ~]# git config --global user.email "[email protected]"
创建并初始化版本库
[root@node1 ~]# mkdir firstgit && cd firstgit/ && git init && ls -ah
Initialized empty Git repository in /root/firstgit/.git/
. .. .git
.git目录作用:跟踪管理版本库
- 所有的版本控制系统,其实只能跟踪文本文件的改动,比如TXT文件,网页,所有的程序代码等等,Git也不例外。版本控制系统可以告诉你每次的改动,图片、视频这些二进制文件,虽然也能由版本控制系统管理,但没法跟踪文件的变化,只能把二进制文件每次改动串起来,也就是只知道图片从100KB改成了120KB,但到底改了啥,版本控制系统不知道,也没法知道。
常规操作
1.把文件添加到仓库中
[root@node1 firstgit]# echo "hello world" > readme.txt
[root@node1 firstgit]# git add readme.txt # 添加到仓库中
[root@node1 firstgit]# git commit -m "write a readme.txt file" #提交并通过-m参数说明
[master (root-commit) e380d2c] write a readme.txt file
1 file changed, 1 insertion(+)
create mode 100644 readme.txt
2.修改文件内容,查询内容和状态并提交
[root@node1 firstgit]# echo "hello eagleslab" > readme.txt
[root@node1 firstgit]# git status # 查询当前git仓库状态,readme.txt 需要添加和提交
# On branch master
# Changes not staged for commit:
# (use "git add ..." to update what will be committed)
# (use "git checkout -- ..." to discard changes in working directory)
#
# modified: readme.txt
#
no changes added to commit (use "git add" and/or "git commit -a")
[root@node1 firstgit]# git diff readme.txt # 变化的内容
diff --git a/readme.txt b/readme.txt
index aa982b7..8d0e700 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1 +1 @@
-hello world\n hello git
+hello eagleslab
[root@node1 firstgit]# git add readme.txt
[root@node1 firstgit]# git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD ..." to unstage)
#
# modified: readme.txt
#
[root@node1 firstgit]# git commit -m "change messages"
[master 7b92afb] change messages
1 file changed, 1 insertion(+), 1 deletion(-)
[root@node1 firstgit]# git status
# On branch master
nothing to commit, working directory clean
3.查询历史记录并版本退回
[root@node1 firstgit]# git log
commit 3efa7f0fc058f00b0a98171fb77b44ab31481c87 # 版本ID
Author: Cokeku <[email protected]>
Date: Mon Mar 18 22:42:38 2019 -0400
add zj
commit 7b92afbb9f118f7ae10c49abc3114e4ee91ed26a
Author: Cokeku <[email protected]>
Date: Mon Mar 18 22:37:05 2019 -0400
change messages
commit e380d2cc936e01e17065408000c42c21f114321a
Author: Cokeku <[email protected]>
Date: Mon Mar 18 22:31:25 2019 -0400
write a readme.txt file
[root@node1 firstgit]# git reset --hard e380d2cc936e01e17065408000c42c21f114321a # 退回指定版本
HEAD is now at e380d2c write a readme.txt file
[root@node1 firstgit]# cat readme.txt
hello world
[root@node1 firstgit]# git reset --hard 3efa7f0fc058f00b0a98171fb77b44ab31481c87
HEAD is now at 3efa7f0 add zj
[root@node1 firstgit]# cat readme.txt
hello eagleslab zhengjiang!
记录每一次的命令:
[root@node1 firstgit]# git reflog
3efa7f0 HEAD@{0}: reset: moving to 3efa7f0fc058f00b0a98171fb77b44ab31481c87
e380d2c HEAD@{1}: reset: moving to e380d2cc936e01e17065408000c42c21f114321a
3efa7f0 HEAD@{2}: commit: add zj
7b92afb HEAD@{3}: commit: change messages
e380d2c HEAD@{4}: commit (initial): write a readme.txt file
- 控制版本历史记录:因为git内部有个Head指针指向当前的版本,如果需要退回版本,只需要将Head指针指向相对应的版本号,并且更新工作区文件。
工作区和暂存区
工作区:当前所在的firstgit目录就是一个工作区
-
.git不算工作区,只是Git的版本库
- 版本库中有暂存区和自动创建的master分支及指向master的一个指针HEAD]
- git add:将修改后文件添加到暂存区
- git commit:将暂存区的所有文件提交到master分支上
- git跟踪的是每次修改而不是文件,如果不将修改添加到暂存区是无法加入commit中的
-
撤销修改
- 场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file
- 场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD
,就回到了场景1,第二步按场景1操作 - 场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,版本退回即可,不过前提是没有推送到远程库
删除文件
[root@node1 firstgit]# git status
# On branch master
# Changes not staged for commit:
# (use "git add/rm ..." to update what will be committed) # 先删除再提交
# (use "git checkout -- ..." to discard changes in working directory) # 将版本库中的最新内容同步到工作区
# deleted: readme.tx
*远程仓库
Git是分布式版本控制系统,同一个Git仓库,可以分布到不同的机器上。有一台机器有一个原始版本库,别的机器可以“克隆”这个原始版本库,而且每台机器的版本库其实都是一样的,并没有主次之分。
1.注册Github账号
2.创建SSH Key
$ ssh-keygen -t rsa -C "[email protected]"
3.登陆Github将id_rsa.pub文件的内容添加到SHH Key页面中
PS:
GitHub需要识别出你推送的提交确实是你推送的,而不是别人冒充的,而Git支持SSH协议,所以,GitHub只要知道了你的公钥,就可以确认只有你自己才能推送。
当然,GitHub允许你添加多个Key。假定你有若干电脑,你一会儿在公司提交,一会儿在家里提交,只要把每台电脑的Key都添加到GitHub,就可以在每台电脑上往GitHub推送了。
-
添加远程仓库
注册登录Github
根据提示信息:- 在命令行中创建新的仓库并关联
- 在命令行中关联已经存在的仓库
- git push命令:把当前分支master推送到远程
-
从远程库克隆
- 先前我们都是先创建本地库然后关联远程库
- 现在最佳实践是先创建远程库然后克隆到本地,但是创建远程库的时候选Initialize this repository with a README,这样GitHub会自动为我们创建一个README.md文件。
分支管理
问题:假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。
分支的作用:创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。
快速合并
创建与合并分支
[root@node1 Shell]# git checkout -b dev
Switched to a new branch 'dev'
[root@node1 Shell]# git branch
* dev
master
[root@node1 Shell]# cat 1.txt
[root@node1 Shell]# echo "This is dev operation" > 1.txt
[root@node1 Shell]# git add 1.txt
[root@node1 Shell]# git commit -m "eagels"
[dev 1a3e0b5] eagels
1 file changed, 2 insertions(+)
[root@node1 Shell]# git checkout master
[root@node1 Shell]# cat 1.txt
[root@node1 Shell]# git merge dev
Updating d55b0d3..1a3e0b5
Fast-forward
1.txt | 2 ++
1 file changed, 2 insertions(+)
[root@node1 Shell]# cat 1.txt
This is dev operation
hello
[root@node1 Shell]# git branch -d dev
Deleted branch dev (was 1a3e0b5)
命令:
查看分支:git branch
创建分支:git branch
切换分支:git checkout
创建+切换分支:git checkout -b
合并某分支到当前分支:git merge
删除分支:git branch -d
冲突合并
[root@node1 Shell]# git checkout -b test
Switched to a new branch 'test'
[root@node1 Shell]# echo "test1" >> 1.txt
[root@node1 Shell]# git add .
[root@node1 Shell]# git commit -m "add test1"
[test 0b919fa] add test1
1 file changed, 1 insertion(+)
[root@node1 Shell]# git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
[root@node1 Shell]# echo "test2" >> 1.txt
[root@node1 Shell]# git add 1.txt
[root@node1 Shell]# git commit -m "test2"
[master fe224bc] test2
1 file changed, 1 insertion(+)
[root@node1 Shell]# git merge test
Auto-merging 1.txt
CONFLICT (content): Merge conflict in 1.txt
Automatic merge failed; fix conflicts and then commit the result.
合并失败:因为现在test分支和master分支同级!
解决:
[root@node1 Shell]# git status
# On branch master
# Your branch is ahead of 'origin/master' by 2 commits.
# (use "git push" to publish your local commits)
#
# You have unmerged paths.
# (fix conflicts and run "git commit")
#
# Unmerged paths:
# (use "git add ..." to mark resolution)
#
# both modified: 1.txt
#
no changes added to commit (use "git add" and/or "git commit -a")
[root@node1 Shell]# cat 1.txt
This is dev operation
hello
<<<<<<< HEAD
test2
=======
test1
>>>>>>> test
修改1.txt冲突的内容,然后再次添加和提交
[root@node1 Shell]# git add 1.txt
[root@node1 Shell]# git commit -m "test12"
[master deedd5e] test12
[root@node1 Shell]# cat 1.txt
This is dev operation
hello
test12
查看分支合并情况:
[root@node1 Shell]# git log --graph --pretty=oneline --abbrev-commit
* deedd5e test12
|\
| * 0b919fa add test1
* | fe224bc test2
|/
* 1a3e0b5 eagels
* d55b0d3 add 1.txt file
* 237e280 Initial commit
Bug分支
环境:当我们正在dev开发新功能的时候,突然有个紧急bug110需要修复,这是我们就需要将当前dev分支stash,然后假设去修改master分支上的bug,然后就需要切换到master分支创建issue-110,进行修复。
创建test分支,修改1.txt文件,然后stash将现场快照
[root@node1 Shell]# git checkout -b test
Switched to a new branch 'test'
[root@node1 Shell]# echo "111" > 1.txt
[root@node1 Shell]# git stash # 打快照
Saved working directory and index state WIP on test: 37e752c money
HEAD is now at 37e752c money
创建issue-111分支,修复bug(修改money.txt)的内容,然后add,commit
[root@node1 Shell]# git checkout -b issue-111
Switched to a new branch 'issue-111'
[root@node1 Shell]# echo "111" > money.txt
[root@node1 Shell]# git add money.txt
[root@node1 Shell]# git commit -m "change 111"
[issue-111 3422006] change 111
1 file changed, 1 insertion(+), 1 deletion(-)
[root@node1 Shell]# git status
# On branch issue-111
nothing to commit, working directory clean
合并分支
[root@node1 Shell]# git merge issue-111
切换回test分支,恢复快照,继续工作
[root@node1 Shell]# git checkout test
Switched to branch 'test'
[root@node1 Shell]# git status
# On branch test
nothing to commit, working directory clean
[root@node1 Shell]# git stash list
stash@{0}: WIP on test: 37e752c money
[root@node1 Shell]# git stash pop # 恢复快照
# On branch test
# Changes not staged for commit:
# (use "git add ..." to update what will be committed)
# (use "git checkout -- ..." to discard changes in working directory)
#
# modified: 1.txt
#
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (ffbba1442a3a3b6cbda32b7ffa3e131f46b60a38)
[root@node1 Shell]# cat 1.txt
111
[root@node1 Shell]# git add 1.txt
[root@node1 Shell]# git commit -m "change 1.txt"
[test a6e4e7c] change 1.txt
1 file changed, 1 insertion(+), 4 deletions(-)
[root@node1 Shell]# git checkout master
Switched to branch 'master'
[root@node1 Shell]# git status
# On branch master
nothing to commit, working directory clean
若要删除一个还未合并的feature分支,可以通过git branch -D 强行删除!
多人协作:
- 查看远程库信息,使用git remote -v
- 本地新建的分支如果不推送到远程,对其他人就是不可见的 从本地推送分支,使用git push origin branch-name,如果推送失败,先用git pull抓取远程的新提交;
- 在本地创建和远程分支对应的分支,使用git checkout -b branch-name origin/branch-name,本地和远程分支的名称最好一致;
- 建立本地分支和远程分支的关联,使用git branch --set-upstream branch-name origin/branch-name;
- 从远程抓取分支,使用git pull,如果有冲突,要先处理冲突。
rebase作用:
- rebase操作可以把本地未push的分叉提交历史整理成直线
- rebase的目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比
标签管理
创建标签
- 命令git tag
用于新建一个标签,默认为HEAD,也可以指定一个commit id; - 命令git tag -a
-m "blablabla..."可以指定标签信息; - 命令git tag可以查看所有标签。
管理标签
- 命令git push origin
可以推送一个本地标签; - 命令git push origin --tags可以推送全部未推送过的本地标签;
- 命令git tag -d
可以删除一个本地标签; - 命令git push origin :refs/tags/
可以删除一个远程标签。
搭建Git服务器
方案1:
[root@node2 ~]# yum install git -y
[root@node2 ~]# adduser git
[root@node2 git]# mkdir .ssh/
放入公钥并初始化:
[root@node2 git]# vim .ssh/authorized_keys
[root@node2 git]# cd /srv/
[root@node2 srv]# git init --bare sample.git
[root@node2 srv]# chown -R git:git sample.git/
克隆仓库:
[root@node1 ~]# git clone git@node2:/srv/sample.git
方案2:
GitLab安装
环境准备:
[root@node1 ~]# yum install -y curl policycoreutils-python openssh-server
[root@node2 ~]# systemctl enable sshd
[root@node2 ~]# systemctl start sshd
[root@node2 ~]# firewall-cmd --permanent --add-service=http
[root@node2 ~]# systemctl reload firewalld
邮箱服务:
[root@node2 ~]# yum install postfix -y
[root@node2 ~]# systemctl enable postfix
[root@node2 ~]# systemctl start postfix
配置YUM源:
[root@node2 ~]# cat > /etc/yum.repos.d/gitlab_ce.repo << EOF
> [gitlab-ce]
> name=Gitlab CE Repository
> baseurl=https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el$releasever/
> gpgcheck=0
> enabled=1
> EOF
[root@node2 ~]# yum makecache
[root@node2 ~]# yum install gitlab-ce -y
[root@node2 ~]# sed -i "s/^external_url.*/external_url 'http:\/\/$Host_IP:8090'/g" /etc/gitlab/gitlab.rb
注意:gitlab本身采用80端口,如安装前服务器有启用80,安装完访问会报错,需更改gitlab的默认端口。
注意:unicorn本身采用8080端口,如安装前服务器有启用8080,安装完访问会报错,需更改unicorn的默认端口。
每次更改后使配置生效:
[root@node2 ~]# gitlab-ctl reconfigure
gitlab 日常管理命令:
gitlab-ctl start
gitlab-ctl stop
gitlab-ctl status
gitlab-ctl restart
gitlab-ctl reconfigure
最后通过浏览器:http://$Host_IP:8090
默认root用户,并且重置密码