git 环境
git 使用
gitEnv:
find ./ -type f -size +100M
sudo apt-get install git git-core
ssh -T git@github.com
git config --global user.name "tanXianQiang"
git config --global user.email "852897652@qq.com"
git config --list
ssh-keygen -C "852897652@qq.com" -t rsa
ssh-agent bash --login -i
ssh-add ~/.ssh/id_rsa
cat id_rsa.pub
# 创建git服务器
一:创建git账号和git用户组
$ sudo adduser git #添加git用户
$ sudo passwd git #添加git的密码
$ sudo groupadd git #添加git用户组
$ sudo usermod -G git git #添加git用户到git用户组
二、创建git仓库
$ cd /srv # srv目录下存放git的仓库
$ mkdir nginx-docs.git # 创建nginx-docs.git目录
$ cd nginx-docs.git
$ git init --bare # bare选项指示该仓库为裸仓库
$ sudo chown -R git:git /srv/nginx-docs.git # 修改权限为git用户
三、禁止git用户登录shell,这样git通过sh服务登录会被拒绝
chsh git
git clone git@<您的 CVM IP 地址>:git仓库路径
五、免密输入的配置
就是通过rsa认证,生成公钥和私钥,然后把客户端的公钥告诉git服务器,具体步骤如下:
在客户端机器上,比如我在windows机器上已经配置用户名和密码,见上一章的git配置说明,
然后打开git bash shell,生成rsa的秘钥对,ssh-keygen –t =rsa命令后一路按回车,此时会在c:/Users/lizhiyong/.ssh/目录下生成id_rsa.pub和id_rsa文件,id_rsa.pub是公钥文件,id_rsa是私钥文件
在git服务器上:
$ su git
$ ssh-keygen –t rsa
$ touch authorized_keys
然后把客户端的id_rsa.pub追加到这个文件里。这样后,
我们就不需要每次都输入git密码了
#git四个区域
在git服务器上:
$ su git
$ ssh-keygen –t rsa
$ touch authorized_keys
然后把客户端的id_rsa.pub追加到这个文件里。这样后,
我们就不需要每次都输入git密码了
#git的工作流程一般是这样的:
1、在工作目录中添加、修改文件;
2、将需要进行版本管理的文件add到暂存区域;
3、将暂存区域的文件commit到git仓库;
4、本地的修改push到远程仓库,如果失败则执行第5步
5、git pull将远程仓库的修改拉取到本地,如果有冲突需要修改冲突。回到第三步
因此,git管理的文件有三种状态:已修改(modified),已暂存(staged),已提交(committed)
#四种状态
Untracked: 未跟踪, 此文件在文件夹中,但并没有加入到git库,不参与版本控制, 通过git add 状态变为Staged。
Unmodify: 文件已经入库且未修改, 即版本库中的文件快照内容与文件夹中完全一致,这种类型的文件有两种去处,如果它被修改, 而变为Modified,如果使用git rm移出版本库, 则成为Untracked文件。
Modified:文件已修改,仅仅是修改,并没有进行其他的操作,这个文件也有两个去处,通过git add可进入暂存staged状态,使用git checkout 则丢弃修改,返回到unmodify状态, 这个git checkout即从库中取出文件,覆盖当前修改
Staged:暂存状态,执行git commit则将修改同步到库中,这时库中的文件和本地文件又变为一致,文件为Unmodify状态。
#分支介绍
git branch # 查看分支
git branch develop # 创建develop分支
git checkout –b feature/FT-123456 # 创建FT-123456的一个feature分支
git checkout develop # 切换分支
git merge feature/FT-123456 # 合并分支
git branch –d feature/FT-123456 # 删除FT-123456的feature分支
git push –u origin hotfix/ISSUE-345678 # 推送分支
#标准流程
Master : 稳定压倒一切,禁止尚review和测试过的代码提交到这个分支上,Master上的代码是可以随时部署到线上生产环境的。
Develop :开发分支,我们的持续集成工作在这里,code review过的代码合入到这里,我们以下要讲的BUG fix和feature开发都可以基于develop分支拉取,修改完之后合入到develop分支。
Feature :功能开发和change request的分支,也即我们每一个feature都可以从devlop上拉取一个分支,开发、review和测试完之后合入develop分支。
Hotfix :紧急修改的分支,在master发布到线上出现某个问题的时候,算作一个紧急布丁。从master分支上拉取代码,修改完之后
合入develop和master分支。
Release :预发布分支,比如0.1、0.2、1.12版本,我们一般说的系统测试就是基于这些分支做的,如果出现bug,则可以基于该release分支拉取一个临时bug分支。
Bug : bug fix的分支,当我们定位、解决后合入develop和Release分支,然后让测试人员回归测试,回归测试后由close这个bug
#github魅力
Repo:项目,绝大多数的开源项目都会放在github上,包括Linus Torvalds参与的linux内核,基于repo可以提issue,可以review code,可以有wiki,branch,tag等等都支持,还可以star和fork这样的repo。
Explore:基于兴趣显示了一些开源项目
Topics:按照主题显示的一些项目,可以选择某个主题继续观察
Trending:流行repo,可以选择语言和周期来显示
Events:显示github官方的一些活动
# 高质量的开源项目
搜索的方法: 关键字
stars:> 1000
fork:>100
语言: java html
ngnix stars:>100
#搭建gitlab
第一步:安装一些依赖软件
sudo apt-get update
sudo apt-get install -y curl openssh-server ca-certificates
sudo apt-get install -y postfix # postfix发送邮件,其它的邮件配置见:https://docs.gitlab.com/omnibus/settings/smtp.html
第二步:添加下载源:
vim /etc/apt/sources.list.d/gitlab_gitlab-ee.list 打开该文件添加:
deb https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/ubuntu xenial main
第三步:安装gitlab
sudo apt-get update
sudo apt-get install gitlab-ce
第四步:配置gitlab
vim /etc/gitlab/gitlab.rb
external_url ‘http://192.168.2.129’ # 把external_url修改成访问的IP,当然更复杂的配置信息可以参考
https://docs.gitlab.com/omnibus/settings/configuration.html#configuring-the-external-url-for-gitlab
gitlab-ctl reconfigure # 开始配置
第五步:启动重启查看状态:
gitlab-ctl restart/start/status/stop # 通过gitlab-ctl help都能查看到该信息
比如gitlab-ctl status,会显示以下信息:
此时我们可以使用gitlab-ctl tail来查看gitlab的服务日志,通过日志可以看到8080端口被别的进程占用了
vim /var/opt/gitlab/gitlab-rails/etc/unicorn.rb # 然后把listen的8080端口改成8088,然后重启gitlab
gitlab-ctl restart
# 配置帮助
$ git help <verb>
$ git <verb> --help
$ man git-<verb>
例如,要想获得config 命令的手册,执行$ git help config
当然,如果你遇到问题也可以查看git的官方文档。https://git-scm.com/book/zh/v2
# 查看commit的内容 --
$ git log # 不带任何参数
$ git log --onelie # 每条日志显示一行
$ git log –[length] # 只显示前面的length条日志
$ git log --skip=[skip] -3 # 跳过前面的skip条日志
$ git log -p # 显示一些统计信息以及文件的改动内容和行信息
$ git log --stat # 显示提交的作者 日期 message 和文件内容统计信息
$ git shortlog # 显示每个author提交commit和多少条commit
按日期
$ git log --after="2018-7-1" # 2018年7月1好之后的所有日志
$ git log –-before="2014-7-1"
按作者
$ git log --author="Dounin"
按照提交信息
$ git log --grep=“issue” # 按照提交本中是否包含issue的日志
按文件
$ git log -- ./src/http/modules/ngx_http_xslt_filter_module.c
按照内容
$ git log -S “ngx_free” # 即所有文件中包含了 ngx_free字符串的修改
按照范围
$ git log <since>..<until> # 比如 git log master..feature这可以显示出自从master分支fork之后,feature分支上所有的提交
$ git show commit-id # 显示commit-id的提交内容,包括所有文件的修改信息
#版本回退 工作空间没有内容
看到git checkout命令就是从本地仓库中或暂存区检出文件,并且覆盖工作目录的内容
$ git checkout branches/stable-1.14 # 检出到branches/stable-1.14分支上,即用1.14分支的内容覆盖了工作区所有内容
$ git checkout 9bfbacdd # 检出到9bfbacdd(commit id)上,即用这个commit 内容覆盖了工作区所有内容
$ git checkout main.cpp # 从暂存区中检出内容,并且覆盖main.cpp文件内容,即尚未添加到暂存区的修改会被丢弃掉
# 工作空间 工作空间有内容
可是上面都是说从git的本地仓库和暂存区里检出内容,然后覆盖掉工作区的内容,即丢弃了本地所有的修改。
那如果是有些内容已经存在工作区了,但是尚未提交到暂存区,即是untracked的内容,那么我们可以使用
git clean命令来删除这些文件,用法如下:
git clean -n :是一次clean的演习,告诉你哪些文件会被删除,记住他不会真正的删除文件,只是一个提醒。
git clean –f :删除当前目录下所有没有track过的文件,他不会删除.gitignore文件里面指定的文件夹和文件,不管这些
文件有没有被track过。
git clean -f <path> :删除指定路径下的没有被track过的文件
git clean -df :删除当前目录下没有被track过的文件和文件夹
git clean -xf :删除当前目录下所有没有track过的文件,不管他是否是.gitignore文件里面指定的文件夹和文件。
好了,如果我们想要放弃本地的所有修改可以:
git checkout . # 注意有一个“.”,会从暂存区里取出所有内容覆盖掉工作区的所有修改,如果连暂存区的内容也不想要
# 则可以git checkout commit-id
git clean -xdf # 删除当前目录下所有的修改
如果我们想要放弃本地某个文件的修改:
git checkout file-name # 从暂存区里
#已经提交到本地仓库
git reset --hard HEAD~{n}就是把HEAD指针回退n
个版本(commit),并且使用该commit的内容覆盖掉
工作区的内容,即丢弃了前面n个commit的修改和当前
工作区的修改。然后调用
git push origin master推送到远程仓库
#远程分支回滚
如果有其它同事基于我们的commit做修改的
话,我们回退版本的时候不想把他的提交给回退
掉,比如记录如右图:
我(lizhiyong)想回滚到5ff5433b这里,但
是king有个提交我不能回滚掉,要保存他的代码,
而且如果有多个同事的修改在在5ff5433b之后的,
那怎么办呢?
比较好的做法就是从5ff5433b拉取一个新的分
支(分支名是reset_to_5ff5433b), 因为这个新分
支不包含我要回滚的代码,此时我们可以把其它同
事的修改手动合并到reset_to_5ff5433b分支,接着
切换到master分支上,使用git merge reset_to
_5ff5433b去合并分支到master上。
git revert d061cb3 # 因为4bff67b是晚于d061cb3的,如果这两个修改的内容有依赖,是会有冲突的(见图一),当然如果
# 想取消这次回退可以使用,git revert --abort
fix conflict # 手动去解决冲突(见图二)
git commit # 然后提交,此时使用git log会发现原理的git commit记录还在,但是增加了一个revert的记录(见图三)
git push # 推送至远程库
$ git checkout -b reset_to_5ff5433b 5ff5433bd1fe4 # 从5ff5433bd1fe4处创建分支,即代码是5ff5433bd1fe4处的代码
$ git show 9d531db98276 # 查看master分支上的其它同事的提交(比如KING),把他的修改在新分支上再修改一遍
$ git commit –a –m “reverted 5ff5433b”
$ git checkout master # 切换到master分支
$ git merge reset_to_5ff5433b
$ git push #推送到远程仓库
# 提交
git commit file1.name file2.name file3.name .. –m “commit messages”
commit指提交修改到本地的仓库里,file*.name指的是带commit的文件 –m后面的内容指提交的信息,即备注
git commit –a –m “commit messeages”
添加的-a参数会把当前暂存区里所有的修改(包括删除操作)都提交,但是那些尚未添加到暂存区的内容是不会提交的,网上有
很多的博客内容说-a参数会把尚未add的文件也提交了,这个说法是错误的。
git commit
我们可能由时候手抖忘记输入-m参数,直接输入了git commit,
于是出现了右边这个界面,即打开了一个vim编辑界面,敲入
“i”键后保存,输入要添加的message后,输入“ESC”按键
退出编辑界面,然后再敲入“:wqa”后会保存message内容,
并且提交此次修改,如果敲入“:q”会取消这次提交。
git commit --amend
这也是我们经常用的命令,他会把此次提交追加到上一次的
commit内容里。
# commit 格式
标题行: 必填, 描述主要修改类型和内容
主题内容: 描述为什么修改, 做了什么样的修改, 以及开发的思路等等
页脚注释: 放 Breaking Changes 或 Closed Issues
message的格式:
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
Type指:
feat: 新特性
fix: 修改问题
refactor: 代码重构
docs: 文档修改
style: 代码格式修改, 注意不是 css 修改
test: 测试用例修改
chore: 其他修改, 比如构建流程, 依赖管理.
scope: commit 影响的范围,即影响的模块或者组件,比如: route, component, utils, build...
subject: commit 的概述, 建议符合 50/72 formatting
body: commit 具体修改内容, 可以分为多行, 建议符合 50/72 formatting
footer: 一些备注, 通常是 BREAKING CHANGE 或修复的 bug 的链接,或者feature等等其余的信息.
使用git cmmit模板来规范提交
1. 在~/.gitconfig文件里添加
[commit]
template=~/.gitmessage
2. 添加~/.gitmessage文件
# git的commitizen
下载对应版本的nodejs包,并安装
https://nodejs.org/en/download/
2. 使用 npm 工具进行全局安装,
npm install commitizen -g
3. 然后在项目目录里,运行下面命令,使其支持 Angular 的 Commit message 格式,
commitizen init cz-conventional-changelog --save --save-exact
以后,凡是用到 git commit 命令,一律改用 git cz ,这时候就会出现选项,来生成符合规范的 commit message 。
4. 如果我们希望每个使用 git 的项目都遵循这个标准,可以使用下面命令进行全局设置。
安装 cz-conventional-changelog ,
npm install -g cz-conventional-changelog
5. 创建一个 .czrc 文件在你的 home 目录,并将 path 指向上面所安装的 commitizen 适配器,
echo '{ "path": "cz-conventional-changelog" }' > ~/.czrc
6. 现在我们可以在每个 git 项目中使用 git cz 提交我们的 commit message 了,当然我们还可以配置Commitlint做自动检测,检查不通过的可以拒绝提交,比较绝吧。
7. 如果我们所有的commit信息都是按照这个格式填写的,在发布版本时,我们就可以使用以下命令生成changelog了
conventional-changelog -p angular -i CHANGELOG.md -s
# 推送分支
git push命令用于将本地分支的更新,推送到远程主机。它的格式与git pull命令相仿。
git push <远程主机名> <本地分支名>:<远程分支名>
注意,分支推送顺序的写法是<来源地>:<目的地>,所以git pull是<远程分支>:<本地分支>,而git push是<本地分支>:<远程分支>。例如:
git push origin master:refs/for/master
如果省略远程分支名,则表示将本地分支推送与之存在”追踪关系”的远程分支(通常两者同名),如果该远程分支不存在,则会被新建。
git push origin master
上面命令表示,将本地的master分支推送到origin主机的master分支。如果后者不存在,则会被新建。
如果省略本地分支名,则表示删除指定的远程分支,因为这等同于推送一个空的本地分支到远程分支。
git push origin :master # 等同于 git push origin --delete master
上面命令表示删除origin主机的master分支。
如果当前分支与远程分支之间存在追踪关系,则本地分支和远程分支都可以省略。
git push origin
上面命令表示,将当前分支推送到origin主机的对应分支。
如果当前分支只有一个追踪分支,那么主机名都可以省略。
git push
# 推送冲突
Git push的时候如果有冲突,会显示如下,此时我们必须去修复这个冲突。
首先我们调用git pull去拉取分支下来(如左下图),然后会在冲突的文件里记录冲突的内容,手动去解决冲突,然后
再git commit 和 git push
# 修改你的提交
此时我们可以先调用git add README.md文件到暂存区,然
后调用git commit –-amend把当前暂存区里的内容合并到上一
次commit里,而且还可以修改上一次提交的message信息。
当然我们除了添加“漏掉”的文件,也可以删除
“误修改”的文件。最后使用git push –fore强制推送修改后的commit
# 修改任意提交的message
$ git rebase –i bed58d54e # 打算从bed58d54e(不包含bed58d54e)之后所有的commit 的message
输入上面一条命令后,会弹出下文这个窗口,上半部分是一些pick命令,下半部分是一些提示内容,不过有意思的是此时的commit内容的排列和git log里的排列是反的,也就是倒序的。如果我们仅仅修改commit message,需要把打算修改的commit的对应pick命令修改为reword,然后保存。
之后会弹出编辑commit message的内容,如果我们
有多处commit需要被修改的话会多次弹出vim编辑窗口。
如果在修改前所有的commit都已经push到远程仓库的话,我们需要使用git push --force强制推送到远程仓库。
# 修改任意的提交内容
上文仅仅说明了修改历史提交的message,但是如果在某个历史提交中少提交内容,比如上文某个源码文件里的内容修改不完整,提交很多天经过严格测试才发现,那么我们就可以使用git rebase的edit命令修改提交内容了。
$ git rebase –i bdc6778948a
上面的命令后我们可以使用edit命令替换pick命令。
保存后,此时git rebase会停止工作,以便我们可以编辑文件和commit message,修改并提交后,可以继续其它的edit命令。在这个过程中我们会使用到以下这两条命令
$ git commit –-amend
$ git rebse --continue
如果在修改前所有的commit都已经push到远程仓库的话,我们需要使用git push --force强制推送到远程仓库。
# commit 合并
在使用git的时候,我们可能针对同一个任务由多次提交,比如我们针对同一个feature可能由多个同事修改了不同部分,但是
多个提交让我们的版本管理显得比较凌乱,此时我们可以合并多个commit为一个。
首先假设我们有三个commit,如左下所示:我们想把最近的三个commit合并为一个commit,那么此时我们可以使用git rebase
命令了,即git rebase –i 4cbeb4248f7, -i后面的参数表示不要合并的commit的hash值。输入命令出现右下图:
可以看到其中分为两个部分,上方未注释的部分是填写要执行的指令,而下方注释的部分则是指令的提示说明。指令部分中由前方的
命令名称、commit hash 和 commit message 组成。
pick 和 squash的意思如下。我们将 ad777ea和a271901这两个commit前方的命令改成 squash 或 s,然后输入:wq以保存并退出
pick 的意思是要会执行这个 commit
squash 的意思是这个 commit 会被合并到前一个commit
退出后会弹出如下界面,即需要我们重新编辑合并后的commit信息,未注释掉的是会包含在commit message里的,按”wqa”保存后即完成了此次commit的合并
# git备份到另一台服务器上
1)设置ssh的免密登录方式:
ssh-kengen –t rsa # 以rsa算法生成密钥对
vim ~/.ssh/id_rsa.pub # 把id_rsa.pub的内容拷贝后放在git仓库的/root/.ssh/authorized_keys里
chmod 400 /root/.ssh/authorized_keys # 在git服务器上设置文件的权限为400
2)书写以下脚本:我们使用ssh协议进行git clone, --mirror是拷贝镜像的意思(不能省掉,因为git仓库有很多的分支和
tag信息)
3)通过crontab添加定时任务:
crontab –e # 在定时任务中添加: 0 0 * * * sh /srv/backup_remote_git.sh,然后保存
systemctl restart cron # 重启cron服务,如果在centos是systemctl restart crond
# 项目依赖
甚至是依赖了第三方的项目,那么我们可以使用git的submodule来管理这些依赖,submodule允许父项目可以有很多的独立的
Git子项目,这些子项目可以单独提交/push/pull等管理,而且父项目中的提交不会影响到子项目。这有很多好处:
1) 把子模块单独作为一个git项目,他们可以独立开发,他们的错误并不会影响到父项目
2) 团队分模块工作在不同git项目上,减少了代码提交的依赖,减少了很多更新操作
X
# 处理突发事件
git stash # 暂存修改
git stash pop # 从缓存里取出修改
# 指定不需要git管理的文件
.gitignore可以提交到远程仓库中,这样这些规则就可以共享给所有的开发人员了,在.gitignore文件中每一行都定义了忽略
的规则
# ------
# 版本回退
#提交
git add <files>
git commit -m "comment"
#历史记录
git log
git log --pretty=oneline
#回退到上一个版本
git reset --hard HEAD^
# 回到未来的某个版本
git reset --hard 1094a
# 记录你的每一次命令
git reflog
# 工作区和暂存区
# 暂存区
git add
# 分支
git commit -m
# 管理修改
#查看工作区和版本库里面最新版本的区别
git diff HEAD -- readme.txt
#撤销修改
# 丢弃工作区的修改
git checkout -- readme.txt
#删除文件
git rm test.txt
git commit -m "remove test.txt"
# ------
# 创建与合并分支
# 创建dev分支,并切换到dev分支
git checkout -b dev
# 查看当前分支
git branch
# 切换回master
git checkout master
#把dev分支的工作成果合并到master分支上
git merge dev
# 删除dev分支
git branch -d dev
#解决冲突
# 切换分支
git switch -c feature1
# 切换到master分支
git switch master
#合并分支
git merge feature1
# 删除feature1
git branch -d feature1
#分支管理策略
# 创建并切换dev
git switch -c dev
# 切换回master
git switch master
# 合并dev分支,禁用Fast forward
git merge --no-ff -m "merge with no-ff" dev
#Bug分支
# 把当前工作现场“储藏”起来
git stash
# 在master分支上修复
git checkout master
#创建临时分支
git checkout -b issue-101
#切换到master分支
git switch master
#完成合并
git merge --no-ff -m "merged bug fix 101" issue-101
# 删除issue-101分支
git branch -d issue-101
# 回到dev分支
git switch dev
#恢复现场
git stash pop
#工作现场存放
git stash list
# 可以多次stash,然后恢复指定的stash
git stash apply stash@{0}
#Feature分支
# 切换分支
git switch -c feature-vulcan
# 切换分支
git switch dev
# 强行删除
git branch -D feature-vulcan
#多人协作
#要查看远程库
git remote -v
#推送主分支
git push origin master
#推送其他分支dev
git push origin dev
#远程抓取分支
git pull
#在本地创建和远程分支对应的分支
git checkout -b branch-name origin/branch-name
#建立本地分支和远程分支的关联
git branch --set-upstream branch-name origin/branch-name
#Rebase
#查看本地分支比远程分支
git log --graph --pretty=oneline --abbrev-commit
git rebase -i [startpoint] [endpoint]
#-----
# 创建标签
# 打一个新标签
git tag v1.0
#查看所有标签
git tag
# 历史打标签
git tag v0.9 f52c633
# git show <tagname>查看标签信息
git show v0.9
# 有说明的标签 用-a指定标签名,-m指定说明文字
git tag -a v0.1 -m "version 0.1 released" 1094adb
# 操作标签
#删除标签
git tag -d v0.1
# 推送某个标签到远程
git push origin v1.0
# 一次性推送全部尚未推送到远程的本地标签
git push origin --tags
# 从远程删除标签
git push origin :refs/tags/v0.9
#显示标签信息
git show v0.1
补充git命令
git merge test --squash
git merge --squash 是用来把一些不必要commit进行压缩,比如说,你的feature在开发的时候写的commit很乱,那么我们合并的时候不希望把这些历史commit带过来,于是使用–squash进行合并,此时文件已经同合并后一样了,但不移动HEAD,不提交。需要进行一次额外的commit来“总结”一下,然后完成最终的合并
参考这个-v进行反选
git log -5 --oneline --name-only | grep -v ‘[ ]’ 那么我过滤出来的就是实实在在的路径。
text=$(git log master ^master_base --name-only --oneline | grep -v ‘[ ]’)
git log master ^master_base --name-only --oneline | grep ^ [ ^ 0-9]
git log master ^master_base --name-only --oneline | grep -v ‘[ ]’
查看本地分支与远程分支得对应关系
git branch -vv
代码出错位置定位: git bisect :http://www.ruanyifeng.com/blog/2018/12/git-bisect.html
关联远端分支
git remote rm origin(删除关联的origin的远程库)
git remote add origin git@gitee.com:
更新git的操作流程
1.
git pull --rebase
git revert
git cherry-pick
git commit --amend --reser-author --no-edit
git pull --rebase
git push