proxy 10.10.11.10
client 10.10.11.11
web1 10.10.11.12
web2 10.10.11.13
proxy:
1. Git安装
]# yum -y install git
]# git config --global user.name "zk"
]# git config --global user.email "349012093@qq.com"
]# git --help
最常用的 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 对象
2. 创建版本库
]# mkdir mymenu
]# cd mymenu/
mymenu]# git init # 初始化仓库
初始化空的 Git 版本库于 /root/mymenu/.git/
初始化了一个空的仓库,目录下多了.git目录
系统自动创建了唯一一个master分支
版本控制系统只能跟踪文本文件的改动,且编码方式是utf-8
3. 文件的基本操作
mymenu]# echo 'Hello World!' > readme.txt
3.1 添加文件到仓库
mymenu]# git add readme.txt
3.2 提交文件到仓库
mymenu]# git commit -m "a new file"
[master(根提交) 17a73da] a new file
1 file changed, 1 insertion(+)
create mode 100644 readme.txt
如果提交的备注写错了,可以用以下命令修改刚刚提交的备注
mymenu]# git commit --amend (进入vim编辑模式)
[master bcd3382] A new file
1 file changed, 1 insertion(+)
create mode 100644 readme.txt
3.3 修改文件
mymenu]# echo '123' > readme.txt
提交文件到仓库
mymenu]# git add readme.txt
mymenu]# git commit -m "change to 123"
[master ae3d174] change to 123
1 file changed, 1 insertion(+), 1 deletion(-)
3.4 每次commit都会生成一个“快照”
查看历史记录
mymenu]# git log
commit ae3d174701f89d8b68ebd143818c81a9717d5963
Author: zk <349012093@qq.com>
Date: Thu Jan 9 07:08:19 2020 +0800
change to 123
commit bcd3382da570951e3ce8cb411adb127f7af8d1bd
Author: zk <349012093@qq.com>
Date: Thu Jan 9 07:02:24 2020 +0800
A new file
git的版本号是用SHA1计算出来的一个16进制数
如果嫌输出信息太多,可以加上--pretty=oneline
mymenu]# git log --pretty=oneline
ae3d174701f89d8b68ebd143818c81a9717d5963 change to 123
bcd3382da570951e3ce8cb411adb127f7af8d1bd A new file
3.5 回退历史版本
mymenu]# git reset
首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交bcd3382...,上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。
回退上一版本
mymenu]# git reset --hard HEAD^
HEAD 现在位于 bcd3382 A new file
这时再次查看历史版本
mymenu]# git log
commit bcd3382da570951e3ce8cb411adb127f7af8d1bd
Author: zk <349012093@qq.com>
Date: Thu Jan 9 07:02:24 2020 +0800
A new file
之前那个版本已经看不到了,这时如果想回到之前那个版本,需要知道版本号,git内部有个指向当前版本的head指针,将指针从当前版本指回去,所以git回退版本特别快
mymenu]# git reset --hard bcd3382
HEAD 现在位于 bcd3382 A new file
[root@proxy mymenu]# git log
commit bcd3382da570951e3ce8cb411adb127f7af8d1bd
Author: zk <349012093@qq.com>
Date: Thu Jan 9 07:02:24 2020 +0800
A new file
3.6 查看历史命令
mymenu]# git reflog
bcd3382 HEAD@{0}: reset: moving to HEAD^
ae3d174 HEAD@{1}: commit: change to 123
bcd3382 HEAD@{2}: commit (amend): A new file
17a73da HEAD@{3}: commit (initial): a new file
3.7 查看状态
mymenu]# git status
# 位于分支 master
无文件要提交,干净的工作区
4. 工作区和暂存区
Git和SVN的一个不同之处就是有暂存区的概念
名词解释:
工作区(Working Directory):指的是在电脑里能看到的目录,比如mymenu文件夹就是一个工作区
版本库(Repository):.git目录,Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
git add 是把需要提交的文件添加到暂存区
git commit 是把暂存区的所有内容提交到当前分支
5. 修改
5.1 修改文件
mymenu]# echo "bbb" >> readme.txt
mymenu]# git add readme.txt
再次修改
mymenu]# echo "ccc" >> readme.txt
提交
mymenu]# git commit -m "test add lines"
[master 9fc3bc0] test add lines
1 file changed, 1 insertion(+)
这时我们发现,第二次的修改未提交,这是为什么呢?
第一次修改-->git add-->第二次修改-->git commit
add将工作区的修改存入暂存区,但是第二次修改并未存入暂存区,git commit只负责把暂存区的修改提交,所以正确的顺序应该是:
第一次修改 --> git add --> 第二次修改 --> git add --> git commit
提交后,查看工作区和版本库里面最新版本的区别:
mymenu]# git diff HEAD -- readme.txt
diff --git a/readme.txt b/readme.txt
index c7ee920..9c2428f 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,3 @@
Hello World!
bbb
+ccc
5.2 撤销修改
丢弃工作区的修改 git checkout -- file
(--很重要,没有--,就变成了“切换到另一个分支”的命令)
mymenu]# git checkout -- readme.txt
命令git checkout -- readme.txt意思就是,把readme.txt文件在工作区的修改全部撤销,这里有两种情况:
一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
总之,就是让这个文件回到最近一次git commit或git add时的状态。
把暂存区的修改撤销掉(unstage),重新放回工作区 git reset HEAD <file>
mymenu]# git reset HEAD readme.txt
mymenu]# cat readme.txt
Hello World!
bbb
git reset命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD时,表示最新的版本。
6 删除文件
工作区中删除文件
mymenu]# rm readme.txt
rm:是否删除普通文件 "readme.txt"?y
此时并没有提交,从版本库同步回来
mymenu]# git checkout -- readme.txt
mymenu]# ls
readme.txt
git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
从版本库删除文件并提交
mymenu]# git rm readme.txt
rm 'readme.txt'
mymenu]# git commit -m "remove readme.txt"
[master 42c64dd] remove readme.txt
1 file changed, 2 deletions(-)
delete mode 100644 readme.txt
7. 分支管理
7.1 介绍
每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支。HEAD严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是当前分支。
一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点:
git-br-initial
每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长。
当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:
git-br-create
Git创建一个分支很快,因为除了增加一个dev指针,改改HEAD的指向,工作区的文件都没有任何变化!
不过,从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变:
git-br-dev-fd
假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并:
git-br-ff-merge
所以Git合并分支也很快!就改改指针,工作区内容也不变!
合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支:
git-br-rm
7.2 master分支添加一个文件
mymenu]# echo "test"> test.txt
mymenu]# git add test.txt
mymenu]# git commit -m "add test.txt"
[master ad6084d] add test.txt
1 file changed, 1 insertion(+)
create mode 100644 test.txt
7.3 创建并切换到分支 dev
mymenu]# git branch dev
mymenu]# git checkout dev
切换到分支 'dev'
查看分支及当前所在分支
mymenu]# git branch
* dev
master
git branch命令会列出所有分支,当前分支前面会标一个*号。
然后,我们就可以在dev分支上正常提交,比如对test.txt做个修改,再提交,dev分支的工作完成后,我们就可以切换回master分支:
mymenu]# echo "aaa" >> test.txt
mymenu]# cat test.txt
test
aaa
mymenu]# git add test.txt
mymenu]# git commit -m "add aaa"
[dev ca10c10] add aaa
1 file changed, 1 insertion(+)
mymenu]# git checkout master
M test.txt
切换到分支 'master'
mymenu]# cat test.txt
test
切换回master分支后,再查看一个test.txt文件,刚才添加的内容不见了!
因为那个提交是在dev分支上,而master分支此刻的提交点并没有变
7.4 合并某个分支到当前分支 git merge <name>
现在,我们把dev分支的工作成果合并到master分支上:
mymenu]# git merge dev
更新 ad6084d..ca10c10
Fast-forward
test.txt | 1 +
1 file changed, 1 insertion(+)
合并后,再查看test.txt的内容,就可以看到,和dev分支的最新提交是完全一样的。
7.5 删除分支 git branch -d <name>
合并完成后,就可以放心地删除dev分支了:
mymenu]# git branch -d dev
已删除分支 dev(曾为 ca10c10)。
删除后,查看branch,就只剩下master分支了:
mymenu]# git branch
* master
7.6 解决冲突
创建并切换到一个新的分支feature1
mymenu]# git checkout -b feature1
M test.txt
切换到一个新分支 'feature1'
在feature1在修改test.txt文件,追加字符"bbb"
mymenu]# cat test.txt
test
aaabbb
提交
mymenu]# git add test.txt
mymenu]# git commit -m "add bbb to aaa"
[feature1 e81e428] add bbb to aaa
1 file changed, 1 insertion(+), 1 deletion(-)
切换到master分支
mymenu]# git checkout master
切换到分支 'master'
在master分支上,在"aaa"后追加"ccc",提交:
mymenu]# cat test.txt
test
aaaccc
mymenu]# git add test.txt
mymenu]# git commit -m "add ccc to aaa"
[master a013cc7] add ccc to aaa
1 file changed, 1 insertion(+), 1 deletion(-)
当两个分支都分别有了新的提交,这种情况下无法进行快速合并,只能试图把各自的修改合并起来,这样有可能会造成冲突:
mymenu]# git merge feature1
自动合并 test.txt
冲突(内容):合并冲突于 test.txt
自动合并失败,修正冲突然后提交修正的结果。
这时我们必须手动解决冲突后再提交,git status可以查看冲突的文件:
mymenu]# git status
# 位于分支 master
# 您有尚未合并的路径。
# (解决冲突并运行 "git commit")
#
# 未合并的路径:
# (使用 "git add <file>..." 标记解决方案)
#
# 双方修改: test.txt
#
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
查看test.txt文件的内容:
mymenu]# cat test.txt
test
<<<<<<< HEAD
aaaccc
=======
aaabbb
>>>>>>> feature1
Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,我们修改如下后保存:
mymenu]# cat test.txt
test
hhhhhhhh
再提交,冲突解决
mymenu]# git add test.txt
ymenu]# git commit -m "conflict fixed"
[master 8ce55da] conflict fixed
用git log --graph --pretty=oneline --abbrev-commit可以看到分支的合并情况,包括分支合并图(--graph)、一行显示(--pretty=oneline)、提交校验码缩略(--abbrev-commit)显示:
mymenu]# git log --graph --pretty=oneline --abbrev-commit
* 8ce55da conflict fixed
|
| * e81e428 add bbb to aaa
* | a013cc7 add ccc to aaa
|/
* ca10c10 add aaa
* ad6084d add test.txt
* 42c64dd remove readme.txt
* 9fc3bc0 test add lines
* bcd3382 A new file
最后,删除feature1分支
mymenu]# git branch -d feature1
已删除分支 feature1(曾为 e81e428)。
7.7 分支管理策略
通常,合并分支时,Git会用快速合并模式(Fast forward),但这种模式下,删除分支后,会丢掉分支信息。
如果用普通合并模式,从分支历史上就可以看出分支信息。
那么,如何使用普通合并模式呢?我们可以用--no-ff参数
mymenu]# git merge --no-ff -m "merge with no-ff" dev
分支策略
master分支是最稳定的,只能用于发布新版本,平时不能在上面进行开发,要在新建的分支上进行开发,比如dev,这时dev是不稳定的,到产品1.0发布时,将dev分支和master分支合并,在master分支上发布1.0版本。
7.8 bug分支
修复bug时,我们会创建一个bug分支进行修复,修复完合并,删除分支。
git stash命令的作用就是将目前还不想提交的但是已经修改的内容进行保存至堆栈中,后续可以在某个分支上恢复出堆栈中的内容。
模拟bug状态
mymenu]# git checkout -b dev
切换到一个新分支 'dev'
mymenu]# cat test.txt
test
hhhhhhhh
mymenu]# echo "mmmmm" >> test.txt
mymenu]# git stash
Saved working directory and index state WIP on dev: 8ce55da conflict fixed
HEAD 现在位于 8ce55da conflict fixed
切换到master去修复bug
mymenu]# git checkout master
切换到分支 'master'
mymenu]# cat test.txt
test
hhhhhhhh
修复了bug后回到dev分支
mymenu]# git checkout dev
mymenu]# cat test.txt
test
hhhhhhhh
我们先查看下stash
mymenu]# git stash list
stash@{0}: WIP on dev: 8ce55da conflict fixed
恢复工作现场
方法1:
用git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除
可以多次stash,恢复指定的stash;
mymenu]# git stash apply stash@{0}
方法2:
用git stash pop,恢复的同时把stash内容也删了:
mymenu]# git stash pop
# 位于分支 dev
# 尚未暂存以备提交的变更:
# (使用 "git add <file>..." 更新要提交的内容)
# (使用 "git checkout -- <file>..." 丢弃工作区的改动)
#
# 修改: test.txt
#
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
丢弃了 refs/stash@{0} (5272bd4e95f7fb8d9c86bad4cbba49f650992a54)
查看恢复
mymenu]# cat test.txt
test
hhhhhhhh
mmmmm
mymenu]# git add test.txt
mymenu]# git commit -m "add mmmm"
[dev 09a7d99] add mmmm
1 file changed, 1 insertion(+)
7.9 不合并删除分支
开发一个新功能,需要新建一个分支。
如果这个功能还未合并就要取消,要使用-D强行删除
mymenu]# git checkout master
切换到分支 'master'
mymenu]# git branch -D dev
已删除分支 dev(曾为 09a7d99)。
7.10 多人协作
当你从远程克隆时,git自动把本地master分支和远程master分支对应起来,远程仓库默认名为origin
查看远程库的信息
mymenu]# git remote
查看远程库的详细信息
mymenu]# git remote -v
7.10.1 推送分支
将本地master分支推送到远程库
如果不推送到远程,本地分支对于其它人就是不可见的
mymenu]# git push origin master
7.10.2 抓取分支
如果本地分支推送到远程库的文件有冲突,推送失败,我们就得先从远程库中抓取最新的提交合并到本地,解决冲突再提交。
mymenu]# git pull
如果git pull报错:没有指定本地分支与远程分支的链接,我们就要手动设置一下
mymenu]# git branch --set-upstream-to=origin/<远程分支名> 本地分支名
7.10.3 Rebase
rebase操作可以把本地未push的分叉提交历史整理成直线;
目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比。
8. 标签管理
切换到需要打标签的分支上
8.1 新建一个标签(默认为HEAD,也可以指定一个commit id)
创建带有说明的标签,用-a指定标签名,-m指定说明文字
git tag <标签名>
git tag <标签名> <commit id>
git tag -a <标签名> -m "备注"
mymenu]# git checkout -b dev
切换到一个新分支 'dev'
mymenu]# git tag latest
8.2 查看标签
mymenu]# git tag
latest
mymenu]# git show latest
commit 8ce55da2adc004c1986e2e31ef6029b8c884ad49
Merge: a013cc7 e81e428
Author: zk <349012093@qq.com>
Date: Thu Jan 9 22:05:02 2020 +0800
conflict fixed
diff --cc test.txt
index c590ac8,0c93a2d..f4d7480
--- a/test.txt
+++ b/test.txt
@@@ -1,2 -1,2 +1,2 @@@
test
- aaaccc
-aaabbb
++hhhhhhhh
PS:标签总是和某个commit挂钩。如果这个commit既出现在master分支,又出现在dev分支,那么在这两个分支上都可以看到这个标签。
8.3 删除标签
创建的标签都只存储在本地,不会自动推送到远程,所以打错的标签可以在本地安全删除;
git tag -d <标签名>
如果标签已经推送到远程,要先从本地删除,再从远程删除
git tag -d <标签名>
git push origin :refs/tags/<标签名>
mymenu]# git tag -d latest
已删除 tag 'latest'(曾为 8ce55da)
8.4 推送标签到远程
推送某个标签到远程 git push origin <tagname>
推送全部尚未推送到远程的本地标签 git push origin --tags
git push origin <标签名>
git push origin --tags