Git git cherry-pick 最佳实践

ibugs · 2015年05月21日 · 最后由 ibugs 回复于 2015年07月28日 · 18240 次阅读

引题

最近公司项目,成都小伙伴,在develop上合并了错误的代码。 然后我们自己的分支上也合并了错误的代码。虽然最终develop的代码回滚了, 错误的代码丢掉,但是自己分支上错误的提交还在,创建merge request 的时,发现一大堆不是自己写的代码,如何解决呢?

cherry-pick

git-cherry-pick - Apply the changes introduced by some existing commits

git-scm#cherry-pick

拙略的英文,翻译为:可以把已经存在提交再次提交。

实战

总体思路如下:找到自己本工单号,本分支提交的commits,在新分值上merge这些commits

第一步: 格式化输出 log

git log 命令可一接受一个--pretty 选项,来确定输出的格式. 如果我们只想输出 hash.

git log --pretty=format:"%h" 

git 用各种 placeholder 来决定各种显示内容:

  • %H: commit hash
  • %h: 缩短的 commit hash
  • %T: tree hash
  • %t: 缩短的 tree hash
  • %P: parent hashes
  • %p: 缩短的 parent hashes
  • %an: 作者名字
  • %aN: mailmap 的作者名字 (.mailmap 对应,详情参照 git-shortlog(1) 或者 git-blame(1))
  • %ae: 作者邮箱
  • %aE: 作者邮箱 (.mailmap 对应,详情参照 git-shortlog(1) 或者 git-blame(1))
  • %ad: 日期 (--date= 制定的格式)
  • %aD: 日期,RFC2822 格式
  • %ar: 日期,相对格式 (1 day ago)
  • %at: 日期,UNIX timestamp
  • %ai: 日期,ISO 8601 格式
  • %cn: 提交者名字
  • %cN: 提交者名字 (.mailmap 对应,详情参照 git-shortlog(1) 或者 git-blame(1))
  • %ce: 提交者 email
  • %cE: 提交者 email (.mailmap 对应,详情参照 git-shortlog(1) 或者 git-blame(1))
  • %cd: 提交日期 (--date= 制定的格式)
  • %cD: 提交日期,RFC2822 格式
  • %cr: 提交日期,相对格式 (1 day ago)
  • %ct: 提交日期,UNIX timestamp
  • %ci: 提交日期,ISO 8601 格式
  • %d: ref 名称
  • %e: encoding
  • %s: commit 信息标题
  • %f: sanitized subject line, suitable for a filename
  • %b: commit 信息内容
  • %N: commit notes
  • %gD: reflog selector, e.g., refs/stash@{1}
  • %gd: shortened reflog selector, e.g., stash@{1}
  • %gs: reflog subject
  • %Cred: 切换到红色
  • %Cgreen: 切换到绿色
  • %Cblue: 切换到蓝色
  • %Creset: 重设颜色
  • %C(...): 制定颜色,as described in color.branch.* config option
  • %m: left, right or boundary mark
  • %n: 换行
  • %%: a raw %
  • %x00: print a byte from a hex code
  • %w([[,[,]]]): switch line wrapping, like the -w option of git-shortlog(1).

第二步: 根据需要输出自己的 commit

根据上述 format,定制

git log -150 --pretty=format:"%h %s %an %aD " | grep wanghao | grep xxxxx

其中 -150 表示输出 150 次的commits

-<1number>, -n <1number>, --max-count=<1number>
Limit the number of commits to output.

  • %h : 缩短的 commit hash
  • %s : commit 信息标题
  • %an : 作者名字
  • %aD : 日期,RFC2822 格式

grep wanghao grep xxxxx 管道符输出

是 wanghao 并且是工单 xxxxx 的 commits

最终输出如下:

98743af [rmxxxxx] Merge branch 'develop' xxxxx
2b48938 [rmxxxxx] rmxxxxxx wanghao 
3320829 [rmxxxxx] rmxxxxxx ****** wanghao Mon, 18 May 2015 14:42:51 +0800
1e09778 [rmxxxxx] rmxxxxxx ****** wanghao Sun, 17 May 2015 18:07:44 +0800

第三步: 运用强大的 cherry-pick

git checkout develop
git pull origin develop
git checkout -b feature/rmxxxxx_wanghao_20150521_xxxx
git cherry-pick 2b48938 3320829 1e09778
git branch -D feature/rmxxxxx_wanghao_20150521_xxxx_tmp

git push origin :feature/rmxxxxx_wanghao_20150521_xxxx
git push origin feature/rmxxxxx_wanghao_20150521_xxxx

bingo!

参考:
ruby-china#个性化你的Git log 输出格式

经常使用 cherry-pick,很好用!

@ery 是的,非常 nice 呢,简直可以称为利器

cherry-pick 的功能,其实,就是把 commit(s),放到你要想的地方。 属于一个高级功能,要求使用者,对 git 有较深的理解。

这个 commit 没有 id 的么?没有提交到远程?

rebase 就直接解决了

#5 楼 @lips feature/rmxxxx_20150521 这个是分支号,刚从 develop checkout 出来的分支,并不是一次提交,所以没有 commit id。还没有提交到远程。

#6 楼 @nouse 是的,完全可以。又提供了一种解法,棒棒的!

Git cherry-pick is great when you know which commits you want (and you know their corresponding hashes) -- it's hard to beat the simplicity it provides.

But what about the situation where you don't know what commits you want? Thankfully git has you covered there as well! We can use interactive rebasing for this -- it's the best way to review a series of commits you're about to rebase.

第一步: 第二步: 第三步:

cherry-pick 容易出事 更倾向于多次拆解小 commit 然后一直向前推进

#9 楼 @so_zengtao 但是,如果你不小心合并和别人错误的分支代码,而且已经向前推进了好多步,最后才发现问题,你怎么解决呢?cherry-pick 就是解决这种情况的。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号