如何打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 <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#    modified:   hk388/Android.mk
#    modified:   hk388/init.rc
# Untracked files:
#   (use "git add <file>..." 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。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章