如何打patch 及git 打patch 失败的处理方法

最近分配了一些打patch的任务。打的那个叫稀巴烂。想必对我很失望。这个过程中学到了如何打patch.

正常来说我们打的git生成的标准patch如果没有没有问题那很好打。

 只需要进入patch对应的代码树,然后执行git am $patchdir/*****.patch   就可以把对应的patch打进去了
 (最好使用git am --keep-cr $patchdir/*****.patch,这样*nix系统和windows的换行问题应该就避免掉了,强烈建议始终加--keep-cr参数)
 (如果很小的patch,行号不对也可以尝试用git am -3  $patchdir/*****.patch  这样会强制merge,但未必每次都可以merge)
 
  往往一个patch下涉及一个git库中的多个文件,很容易失败。如果失败了可以用git am --abort,放弃此次的patch。这样本次patch操作失效。但毕竟patch abort了,并没有打上,没有解决我们的问题。
   正如你所见,如果冲突发生,git只是输出上述信息,然后就停下来。一个小冲突会导致整个patch都不会被集成。
打patch执行:   git am --keep-cr ../94.21/device/common/0025-build-recovery.img-after-boot.img-was-generated.patch

报错如下:
Applying: build boot-with-sig.img after boot.img was generated
/home/ronny/mypatch/mydevice/.git/rebase-apply/patch:51: trailing whitespace.
$(PRODUCT_OUT)/boot.toc: $(PRODUCT_OUT)/boot-with-sig.img $(SECURE_SDK_DIR)
error: patch failed: hk388/hk388.mk:167
error: hk388/hk388.mk: patch does not apply
Patch failed at 0001 build boot-with-sig.img after boot.img was generated
When you have resolved this problem run "git am --resolved".
If you would prefer to skip this patch, instead run "git am --skip".
To restore the original branch and stop patching run "git am --abort".
 简单的方法
 处理这种问题的最简单方法是先使用 git am --abort,然后手动的添加此patch, patch -p1 < PATCH,手动解决掉代码冲突,最后使用 git commit -a 提交代码。但是这样做有个问题就是你会失去PATCH中原本包含的commit信息(比如From,Date,Subject,Signed-off-by等)。

这里需要注意的是手动解决错误在用patch -p时注意层数的问题,怎么确定层数呢?

参数-p来指定从第几层开始比较。比如有一个patch文件的补丁头是这样的:

代码:
--- old/modules/pcitableMon Sep 27 11:03:56 1999+++ new/modules/pcitableTue Dec 19 20:05:41 2000
如果使用参数-p0,就表示从当前目录,找一个叫作new的目录,在它下面找一个叫modules的目录,再在它下面找一个叫pcitableMon的目录。
如果使用参数-p1,就表示忽略第一层,从当前目录找一个叫modules的目录,在它下面找一个叫modules的目录。这样会忽略掉补丁头提到的new目录。
依此类推。

应该有一种更聪明的方法。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
即:在 .git/rebase-apply 目录下,存放着相应的补丁文件,名字是“0001” (在更新的git版本中,存放补丁文件的目录名有所改变,这里使用的git版本是 1.7.9.5)。
事实上,你可以使用 git apply 命令打patch(git apply 是git中的patch命令)。如同使用 patch -p1 命令时一样,然后手动解决代码冲突(检视生成的 .rej 文件,与冲突文件比较,修改冲突内容,并最终把文件加入到index中):
 $ git apply PATCH --reject    (这里的PATCH即为.git/rebase-apply 目录下的0001,如果我们输入git am --abort那么。git下就会清除掉rebase-apply目录,属于白玩了)
$ edit edit edit
(译注:根据.rej文件手动解决所有冲突)
$ git add FIXED_FILES
$ git am --resolved   

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
eg:现在来处理上面patch failed问题:
ronny@ronny:~/mypatch/mydevice$ git apply .git/rebase-apply/     (提示中的0001即为我们要的patch)
0001               applying           final-commit       keep               msg                next               patch              scissors           threeway           
abort-safety       apply-opt          info               last               msg-clean          no_inbody_headers  quiet              sign               utf8               
ronny@ronny:~/mypatch/mydevice$ git apply .git/rebase-apply/0001 --reject
.git/rebase-apply/0001:64: trailing whitespace.
$(PRODUCT_OUT)/boot.toc: $(PRODUCT_OUT)/boot-with-sig.img $(SECURE_SDK_DIR)
Checking patch

...
....
.....
...
..
....
error: patch failed: hk388/hk388.mk:167
Applying patch.....
Rejected hunk #1.
Rejected hunk #2.
Rejected hunk #3.
Applying patch hk388/hk388.mk with 1 rejects...
Rejected hunk #1.
ronny@ronny:~/mypatch/mydevice$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 22 commits.
#
# Changes not staged for commit:
#   (use "git add ..." to update what will be committed)
#   (use "git checkout -- ..." to discard changes in working directory)
#
#    modified:   hk388/Android.mk
#    modified:   hk388/init.rc
# Untracked files:
#   (use "git add ..." to include in what will be committed)
#
#    hk388/init.rc.rej 
#    hk388/hk388.mk.rej
nothing added to commit but untracked files present (use "git add" to track)
这样就产生了2个.rej。然后手动解决代码冲突(检视生成的2个 .rej 文件,与冲突文件比较,修改冲突内容,并最终把文件加入到index中):

提示:上面的modified:   hk388/Android.mk 在下面并没有hk388/Android.mk.rej说明这个文件的的修改是ok的,并没有冲突
ronny@ronny:~/mypatch/mydevice$ vim hk388/Android.mk hk388/Android.mk.rej -O    (-O  大O是纵向打开两个窗口,小o是横向打开两个窗口)
然后看hk388/Android.mk.rej涉及到要改的内容,在 hk388/Android.mk改掉就好
最后git add hk388/Android.mk
     git add hk388/init.rc
     git add hk388/hk388.mk

  git am --resolved  
(完毕)

     
 就这么简单!
想多一些解释,好吧。git am 并不改变index,你需要使用 git apply --reject 打patch(patch保存在 .git/rebase-apply中我这里叫0001),手动解决代码冲突,
(译注:使用 git status 列出所有涉及文件),把所有文件(不仅仅是引起冲突的文件)添加到(git add)index,最后告诉 git am 你已经解决(--resolved)了问题。
这样做的好处是你不需要重新编辑commit信息。而且,如果你正在打的是一系列patch(就是说你在打的是多个patch,比如 git am *.patch)你不需要使用 git am --abort,然后又 git am。

你可能感兴趣的:(BuildRelease,Git/GitHub)