Git简明手册
以下都是常用的操作,并做了一些通用的规范性要求。
有些操作适应于developer,有些适用于version manager。
准备工作
配置个人本地git变量
- 配置邮箱
$ git config --global user.name eric
$ git config --global user.email eric@163.com
- 配置快捷命令
$ git config --global alias.co checkout
$ git config --global alias.ci commit
$ git config --global alias.st status
$ git config --global alias.br branch
$ git config --global alias.hist=log
--pretty=format:'%h %ad | %s%d [%an]' --graph
--date=--date=format:'%A %Y-%m-%d %H:%M:%S'
- 配置默认日志编辑器
# 配置为atom
$ git config --global core.editor "atom --wait"
# 也可以配置其他的,需要设置环境变量
# 提交操作时,一律用一下命令,详细填写comment
$ git ci
从这里开始项目
Clone项目
$ git clone http://github.com/eric/test.git
配置本地忽略文件
# 有些本地的文件,你并不想看到它,更不想加入到版本管理,
# 建立忽略文件,git就不会显示他们。
$ touch .gitignore
$ vi .gitignore
内容类似:
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
*.zip
*.tar.gz
*.rar
#project files #
.classpath
.project
.settings/*
.tern-project
建立本地的远程分支
$ git co --track origin/dev
$ git co --track origin/uat
$ git co --track origin/feature/groupcc
# 从此,向远程推送只需:
git push
正确的开发姿势
# 就是开始之前建立分支,基于分支开发,不要直接在git仓库的分支上开发。
# 基于dev,建立新需求分支
$ git co dev
$ git co -b feature/cc606
# 基于uat,建立bug修复分支
$ git co uat
$ git co -b hotfix/cc606_1
# 把本地开发分支的程序,推送到远程仓库,请管理员合并到dev或uat主分支
$ git push origin feature/cc606:feature/cc606
$ git push origin hotfix/cc606_1:hotfix/cc606_1
# 然后登陆gitlab,建立merge request
一个需求的开发,在本地产生了上百次commits,但仓库关注的是结果
# 管理员会拒绝你这些垃圾日志,只要看到最终结果
# 这时候你可以把你所有的commit合并为一次提交,这样就不会有凌乱的日志
$ git co dev
# 重新拉取一下最新代码
$ git pull --rebase
# 开始合并
$ git merge --squash feature/cc606
# 这样就会把feature/cc606的修改,在本地产生待提交的记录,只要提交
$ git ci -am "req-cc606 - 增加工号必录项"
# 以上merge可能产生conflict,另议
拉取和推送
# 拉取最新代码
$ git pull origin
# 推送到仓库
$ git push origin
比较差异
# 比较不在暂存区的文件与上个版本的区别
$ git diff
# 比较在暂存区的文件与上个版本的区别
$ git diff –-cached
# 比较不在和在暂存区的文件与上个版本的区别
$ git diff head
# 比较本地分支和远程分支的差异
$ git log local_branch..origin/remote_branch
$ git diff local_branch origin/remote_branch
怎么查看某个commit的文件列表
$ git show --name-only 1fc253bd
或者
$ git diff-tree --name-only -r 1fc253bd
怎么查看某个commit下,仓库的所有文件
$ git ls-tree --name-only -r 1fc253bd
怎么查看某个文件的变更历史
$ git log --pretty=oneline filename
怎么比较一个文件不同的历史版本差异
# 先查看文件的变更历史
$ git log --pretty=oneline filename
d34a3eb745f783bb61ed8f03a47b6c79c62d343c 代码调整
ea08e3209ea78329696654dfe8ab79c790d9ed60 调整
6d9e65c570aae4e47fd9895e91dda0672c5261b9 修改字符集 GBK->UTF-8
78cb2ba9f163f312c51b30813335b8ad1e9ec5d4 初始化
$ git diff d34a3eb7 ea08e320 filename
如何导出两个版本之间的变更文件
$ git diff 8038f96a b74cc370 --name-only | xargs tar -czvf you_tar.tar.gz
或者(windows下可能没有zip命令)
$ git diff rv1 rv2 –name-only|xargs zip diff.zip
如何导出某个版本的所有文件到指定目录
$ git archive b74cc370 | tar xC output_dic
如何导出某个版本的特定文件到指定目录
$ git archive b74cc370 filename | tar xC output_dic
当我的代码与别人冲突,如何合并版本时以别人的版本为准
# 项目前期版本变化较大时,有时候你希望以最新的更改覆盖,这时很实用
$ git merge --squash feature/groupcc --strategy-option=theirs
当我的代码与别人冲突,如何合并版本时以自己的版本为准
# 两个人做同一个方案,你的方案更优时,可以这样做
$ git merge feature/groupcc --strategy-option=ours
或者
$ git merge feature/groupcc --s ours
如何仅合并某个分支上的某个特定的commit到当前分支
如仅把下图d1到d2的修改合并到m1
git co dev
git cherry-pick d2
新版本发布时,你可能希望打个标签,以后可以随时回顾历史需求的提交
$ git tag -a v_cc606 -m "cc606需求 - 增加工号必录项"
# 推送到远程
$ git push origin v_cc606
commit后,发现漏个文件,或者message写的不合适,修改最后一次提交
$ git add file_another
$ git ci --amend
有时候你希望根据关键字查找变更的历史
$ git log --grep=keyword
有时候你希望根据committer或者author查找变更的历史
$ git log --committer=eric
$ git log --author=eric
正在开发一个需求,突然Bug降临!?
经常有这样的事情发生,当你正在进行项目中某一部分的工作,里面的东西处于一个比较杂乱的状态,而你想转到其他分支上进行一些工作。问题是,你不想提交进行了一半的工作,否则以后你无法回到这个工作点。解决这个问题的办法就是git stash命令
# 临时保存当前的工作(加入当前未完成的需求为cc606)
$ git stash save "cc606"
# 多次stash以后,列出所有的stash
$ git stash list
$ git stash list
stash@{0}: On feature/groupcc: cc606
stash@{1}: WIP on feature/groupcc: ebec8f2d Merge branch
'feature/groupcc' into 'feature/groupcc'
# 如果完成了bug修改,要继续需求开发,取出stash内容
$ git stash apply stash@{0}
# 以上从stash恢复应用的行为,可能与你已经修复的bug程序产生conflict,
# 你需要手工处理冲突
# 当然以下方式可以避免恢复时产生冲突,但最终合并版本时,你还是要处理潜在冲突
# 在指定stash上建立新分支
$ git stash branch bs stash@{0}
版本管理的约定
- 一切皆分支
- 无论需求还是bug都要基于某个基线分支,建立新的开发分支
- 开发完成后推送到gitlab,建立merge request
- 随后可以删除分支
- 关于编码
- 一切程序和配置文件等用UTF-8编码
- 提交的comment注释也要用UTF-8编码
-
comment标准化
- 提交comment,用git ci,详细填写提交日志,不要用git ci -m
- comment的标题要简洁、清晰,以后版本关联和查找非常方便
-
需求按照:req-cc606:增加工号必录项,具体示例如下:
req-cc606:增加工号必录项
--------此处空一行-------
增加手机号必录项,修改了查询、维护功能。
此外,还修改了人员信息导出报表功能。
-
itfix按照:itfix-FN001-cc606:调整维护界面校验,具体示例如下:
itfix-FN001-cc606:调整维护界面校验
--------此处空一行-------
维护界面校验没有考虑空指针情况。
无法关联到具体需求的itfix,按照:itfix-FN001:银保跑批报空指针
格式化日志
-
有了规范的日志格式,查询历史就非常方便了:
$ git log --grep "分支"
-
-
bug修复流程
- 生产的bug,基于master分支建立修复分支
- 修复后,合并到uat、dev分支
- uat的bug,基于uat分支建立修复分支
- 修复后,合并到dev分支
- 生产的bug,基于master分支建立修复分支
-
关于建立几个分支的问题
- 生产、uat、集成测试分别建立分支,master、uat、dev
- master、uat、dev都要保护起来,不允许开发人员随意提交,否则版本混乱
- 开发人员的提交通过merge request合并到主分支
- 关于发布
- 每次发布后,建立一个tag,标记这次发布,建议以格式release_req-cc606命名,通过tag的名字能知道发布的内容
- 关于一个分支上的版本交叉问题
- 无论是什么版本管理工具,按照需求的提交顺序上线至关重要,建议宣导发到UAT的需求要同时上线,没有积压
- 现实是残酷的,一般都会有交叉,如有A、B、C三个需求在dev分支,产生了A、B、C三个commit,来回几次bug修复可能commit历史为:A、B、C、A1、C1、B1、A2、B2,这时候你可能像使用svn一样进行合并,需要用到cherry-pic和冲突解决相关的技巧