AboutFE icon indicating copy to clipboard operation
AboutFE copied to clipboard

23、Git相关

Open CodingMeUp opened this issue 7 years ago • 2 comments


Git项目使用规范一-约定

前提:Git项目管理中存在许多不规范的使用方法,经常使项目中出现一些不必要的工作量,特定义一份Git使用规范,要求一处五组相关同学强制执行

[TOC]

一. 开发前

// 本地git配置core.autocrlf,默认换行统一使用LF,不改变远程
git config --global core.autocrlf input  

// 提取远程项目数据
git checkout master
git pull
git branch feature/user_import
git push origin feature/user_import

说明:在开始新开发时,检出生产的最新代码,各自进行创建功能模块分支(下面简称功能分支),并立即提交git 其它要求:

  • git commit 时message必须提供比较详细的功能修改
  • 每次commit必须是已经可以运行的功能,不能出现阻断或异常情况,如下班前还不能运行,需要在message中说明出来
  • 要求频繁进行commit操作,尽量一个小功能完成就commit
  • 每天下班前汇总所有commit,PUSH到远程
// 如果是功能性增加 提交的COMMIT第一个单词为UPDATE
git add .
git commit -m 'UPDATE 增加了XXX功能,在XXX地方使用'
git push
// 如果是修改BUG  提交的COMMIT第一个单词为FIX
git add .
git commit -m 'FIX 修正了XXX导致的XXX错误'
git push

CRLF错误解决方法

二. 提交develop自测

git checkout develop
git merge feature/user_import

说明:提交开发环境自测时,直接合并功能分支即可,自测发现问题,还是需要在功能分支上修改,并再merge到develop提交开发环境

三. 自测结束发测试环境

  • 切记不要merge develop
  • 如果有测试环境则见下:
git checkout release/debug
git merge feature/user_import
  • 如果没有,则见下:
git branch release/debug
git merge feature/user_import

说明:切记只把功能分支merge到release/debug环境进行测试

四. 测试完成

正常情况下,可能有多个测试版本,需要如下

git checkout master
git merge feature/user_import
// 然后删除分支
git push origin :feature/user_import
git branch -D feature/user_import

如果只有一个团队在测试,那可以如下

git checkout master
git merge release/debug
// 然后删除分支
git push origin :feature/user_import
git branch -D feature/user_import

说明:尽量还是只merge功能分支到master

五. 本地回滚

// 回滚到commit-id,将commit-id之后提交的commit都去除
git reset --hard commit-id
// 将最近3次的提交回滚
git reset --hard HEAD~3
// 还原本地修改并没有提交的文件
git checkout .
// 删除本地新增并没有提交的文件与文件夹
git clean -df

六. 远程回滚

这个是重点要说的内容,过程比本地回滚要复杂 原理:先将本地分支退回到某个commit,删除远程分支,再重新push本地分支 操作步骤:

git checkout the_branch
git pull
// 备份一下这个分支当前的情况
git branch the_branch_backup
// 把the_branch本地回滚到the_commit_id
git reset --hard the_commit_id 
// 删除远程 the_branch
git push origin :the_branch
// 用回滚后的本地分支重新建立远程分支
git push origin the_branch 
// 如果前面都成功了,删除这个备份分支
git push origin :the_branch_backup 

如果使用了gerrit做远程代码中心库和code review平台,需要确保操作git的用户具备分支的push权限,并且选择了 Force Push选项(在push权限设置里有这个选项)

另外,gerrit中心库是个bare库,将HEAD默认指向了master,因此master分支是不能进行删除操作的,最好不要选择删除master分支的策略,换用其他分支。如果一定要这样做,可以考虑到gerrit服务器上修改HEAD指针。。。不建议这样搞

CodingMeUp avatar Dec 20 '17 03:12 CodingMeUp


Git项目使用规范二-后悔药

前提:项目中多成员同步代码时,由于理解及技术生疏等问题,会导致代码丢失或被合并,或被强制合并,这时候就需要对项目代码进行回滚

情况一:代码commit后发现错误

# 这种情况比较简单,只要本地回滚,删除远程,再推送即可
# 回滚到指定代码
git reset --hard xxxx
# 删除远程分支
git push origin :xxxx
# 推送远程
git push origin xxxx

情况二:代码多次commit后发现中间有错误的commit,想直接删除某些commit

一、操作

1.rebase命令

对于git rebase, 你亦可以选择进行交互式的rebase。这种方法通常用于在向别处推送提交之前对它们进行重写。

2.功能

交互式rebase提供了一个简单易用的途径让你在和别人分享提交之前对你的提交进行分割、合并或者重排序。

3.优点

在把从其他开发者处拉取的提交应用到本地时,你也可以使用交互式rebase对它们进行清理。

4.参数

如果你想在rebase的过程中对一部分提交进行修改,你可以在'git rebase'命令中加入'-i'或'--interactive'参数去调用交互模式。

# 这个命令会执行交互式rebase操作,操作对象是那些自最后一次从origin仓库拉取或者向origin推送之后的所有提交。
$ git rebase -i origin/master
# 若想查看一下将被rebase的提交,可以用如下的log命令:
$ git log github/master..
# 一旦运行了'rebase -i'命令,你所预设的编辑器会被调用,其中含有如下的内容:
/**
pick fc62e52 added file_size
pick 9824bf1 fixed little thing
pick 21d83a5 added number to log
pick 71b9da6 added the apply command
pick c364051 Revert "added file_size" - not implemented correctly

# Rebase f408319..b04dc3d onto f408319
#
# Commands:
#  p, pick = use commit
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
**/
/**
这些信息表示从你上一次推送操作起有5个提交。每个提交都用一行来表示,行格式如下:
(action) (partial-sha) (short commit message)
现在你可以将操作(action)改为'edit'(使用提交,但是暂停以便进行修正)或者'squash'(使用提交,但是把它与前一提交合并),默认是'pick'(使用提交)。你可以对这些行上下移动从而对提交进行重排序。当你退出编辑器时,git会按照你指定的顺序去应用提交,并且做出相应的操作(action)。
**/

二、说明

1.pick操作

如果指定进行'pick'操作,git会应用这个补丁,以同样的提交信息(commit message)保存提交。

2.squash操作

如果指定进行'squash'操作,git会把这个提交和前一个提交合并成为一个新的提交。这会再次调用编辑器,你在里面合并这两个提交的提交信息。所以,如果你(在上一步)以如下的内容离开编辑器:

pick   fc62e55 added file_size
squash 9824bf4 fixed little thing
squash 21d80a5 added number to log
squash 76b9da6 added the apply command
squash c264051 Revert "added file_size" - not implemented correctly

你必须基于以下的提交信息创建一个新的提交信息:

# This is a combination of 5 commits.
# The first commit's message is:
added file_size
# This is the 2nd commit message:
fixed little thing
# This is the 3rd commit message:
added number to log
# This is the 4th commit message:
added the apply command
# This is the 5th commit message:
Revert "added file_size" - not implemented correctly
This reverts commit fc62e5543b195f18391886b9f663d5a7eca38e84.

一旦你完成对提交信息的编辑并且退出编辑器,这个新的提交及提交信息会被保存起来。

3.edit操作

如果指定进行'edit'操作,git会完成同样的工作,但是在对下一提交进行操作之前,它会返回到命令行让你对提交进行修正,或者对提交内容进行修改。 例如你想要分割一个提交,你需要对那个提交指定'edit'操作:

pick   fc62e55 added file_size
pick   9824bf4 fixed little thing
edit   21d80a5 added number to log
pick   76b9da6 added the apply command
pick   c264051 Revert "added file_size" - not implemented correctly

你会进入到命令行,重置(reset)该提交,然后创建两个(或者更多个)新提交。假设提交21d80a5修改了两个文件,file1和file2,你想把这两个修改放到不同的提交里。你可以在进入命令行之后进行如下的操作:

$ git reset HEAD^
$ git add file1
$ git commit 'first part of split commit'
$ git add file2
$ git commit 'second part of split commit'
$ git rebase --continue

现在你有6个提交了,而不是5个。 4.丢弃提交操作 交互式rebase的最后一个作用是丢弃提交。如果把一行删除而不是指定'pick'、'squash'和‘edit''中的任何一个,git会从历史中移除该提交。

情况三:代码不仅多次commit,而且还附带了merge、rebase等,这种情况最糟糕,用rebase已经无法处理

这种情况需要使用补丁的形式,一般来说最好是一个一个补丁的打,然后回滚再把补丁打回,如果发现有多个commit是可以合并的,就先使用情况二来合并多个commit,再打补丁,这时候补丁数量就变很少了

一、先合并正确的分支(补丁过多的情况下使用合并commit,如果补丁较少可以忽略这步)

git rebase -i xxxx 然后可以选择抛弃某个commit,如果更无语的话,得再回滚,这个参考情况二

二、合并后创建补丁

#创建最近的一个commit的补丁
git format-patch HEAD~
#如果是两个呢?
git format-patch HEAD~~ 
#如果是三个呢?
git format-patch HEAD~3

三、然后就是回滚

git reset --hard xxxx

四、最后就是打补丁提交

第一步检测补丁有无问题
$ git apply --check xxx.patch
能检测出现的问题有以下几种例子:
 
1. error: cannot apply binary patch to 'xxx' without full index line
xxx一般会是bin/png/gif等等二进制文件 具体的原因就是patch中有指明要打上xxx文件,但是这个文件并不包含在这个patch中,仅仅是有一个名字存在其中。遇到这个问题要重视。
 
2. error: core/java/android/provider/Settings.java: patch does not apply
出现这种一般会是补丁冲突,这种一般是强制打上补丁(使用--reject)后根据产生的*.rej文件来手动解决冲突。
 
3. warning: core/java/android/view/View.java has type 100644, expected 100755
出现这种警告一般是文件内没有冲突,但是文件的权限发生变动。一般没有影响。
 
 
第二步强制打补丁
$ git apply --reject xxx.patch
执行了这一步后会产生什么样的结果,我对第一步的冲突来对应说明。
 
1.这种问题一般是制作补丁的开发人员没有将二进制文件制作到patch中云,对于这种情况不会有任何的提示,因为patch中源资源文件都没有,Git也没有什么招术来解决。最好的方法是联系补丁提供者。
 
2.这种情况是由于git apply是对比补丁中前后几行代码,如果没有出现在目标文件中,那么这就是冲突。这个是比较经常出现的,对于这种情况会生成*.rej文件,可以find ./ -name *.rej找到这些冲突的补丁,手动打上就好。
 
3.可以考虑忽略。
 
目前就这些,遇到新的问题再补充。

git am -3 -k后如果有冲突,不要执行git checkout。如果不愿意修改冲突文件,佯装修改一下,添加进去才能进行下一步。
git --git-dir=../other_proj_dir/.git format-patch -k -1 --stdout xxxxxxxxxxxxxxxxxx | git am -3 -k
git am同样有--reject选项,添加这个选项可以将能打上的补丁先打上,冲突的文件生成*.rej文件。

CodingMeUp avatar Dec 20 '17 03:12 CodingMeUp


Gerrit

前提:工程院增加提高代码质量,需要所有项目迁移Gerrit,以便做CodeReview的管理,由于增加Gerrit后,之前Git项目管理方案并不适用,重新规范一份

[TOC]

一. 开发前

先开启项目的merge权限 image

如果无merge权限,后面用rebase替换

// 本地git配置core.autocrlf,默认换行统一使用LF,不改变远程
git config --global core.autocrlf input  

// 提取远程项目数据
git checkout master
git pull
git branch feature/user_import

说明:在开始新开发时,检出生产的最新代码,各自进行创建功能模块分支(下面简称功能分支),并立即提交git 其它要求:

  • git commit 时message必须提供比较详细的功能修改
  • 每次commit必须是已经可以运行的功能,不能出现阻断或异常情况,如下班前还不能运行,需要在message中说明出来
  • 要求频繁进行commit操作,尽量一个小功能完成就commit
  • 由于使用了gerrit,不建议推送远程
// 如果是功能性增加 提交的COMMIT第一个单词为UPDATE
git add .
git commit -m 'UPDATE 增加了XXX功能,在XXX地方使用'
git push
// 如果是修改BUG  提交的COMMIT第一个单词为FIX
git add .
git commit -m 'FIX 修正了XXX导致的XXX错误'
git push

CRLF错误解决方法

二. 提交develop自测

git checkout develop
git merge feature/user_import
git push origin head:refs/for/develop

说明:提交开发环境自测时,直接合并功能分支即可,并推送远程让主程CodeReivew,CodeReview发现问题,打回重新修改,并重新提交,没问题则评分并发布

三、审核不通过后如何处理

abandon后,客户端如果没修改是不能重新push的

三. 自测结束发测试环境(推送测试环境,直接push,不需要再review)

  • 切记不要merge develop
git checkout release/debug
git merge --no-ff feature/user_import
gitdir=$(git rev-parse --git-dir); scp -p -P 29418 [email protected]:hooks/commit-msg ${gitdir}/hooks/
git commit --amend
git push origin head:refs/for/release/debug

四. 测试完成(推送主分支上,直接push,不需要再review)

正常情况下,可能有多个测试版本,需要如下

git checkout master
git merge --no-ff feature/user_import
gitdir=$(git rev-parse --git-dir); scp -p -P 29418 [email protected]:hooks/commit-msg ${gitdir}/hooks/
git commit --amend
git push origin head:refs/for/master
// 然后删除分支
git branch -D feature/user_import

五. 本地回滚

// 回滚到commit-id,将commit-id之后提交的commit都去除
git reset --hard commit-id
// 将最近3次的提交回滚
git reset --hard HEAD~3
// 还原本地修改并没有提交的文件
git checkout .
// 删除本地新增并没有提交的文件与文件夹
git clean -df

六. 代码审核

Review需要多个处理,Review分数达到2分以上才能通过,只有Owner才能评两分 Review不通过,代码存在大量需要修改的,直接abandon

  1. 只能对一个提交abandon而不是一个文件;
  2. 只能对一个open提交abandon,merge提交(已经submit)只能是revert

CodingMeUp avatar Dec 20 '17 03:12 CodingMeUp