Git rebase 的應用經驗 .

為了玩 Android,學會了 git 的初步使用。不過僅止於基本的 git checkout、git log、git diff、git status、git commit 等。

這幾天為了協助同事將 Android 移植到廠商的板子上,必須將廠商提供的 kernel 與 Android kernel 做結合。為此請教一些 git 高手。經過一番練習,總算對 git rebase 的使用有了初步的掌握。也漸漸了解了 git 的強大威力,為什麼高手都愛用… 特別將這段經驗記載在這邊,給有興趣的人參考。

有兩個 git repositories 要做合併。一個是廠商提供的 kernel:

git://git.kernel.org/pub/scm/linux/kernel/git/kki_ap/samsung-ap-2.6.git

另一個是 Android 的 kernel:

git://android.git.kernel.org/kernel/common.git

首先,先建立一個工作目錄

$ mkdir kernel-git

$ cd kernel-git

$ git init

Initialized empty Git repository in /home/cwhuang/git/kernel-git/.git/

然後加入兩個遠端的 repositories:

$ git remote add samsung git://git.kernel.org/pub/scm/linux/kernel/git/kki_ap/samsung-ap-2.6.git

$ git remote add android git://android.git.kernel.org/kernel/common.git

將遠端 repositories 的資料取回:

$ git fetch samsung

remote: Counting objects: 11677, done.

remote: Compressing objects: 100% (2462/2462), done.

remote: Total 10383 (delta 7976), reused 10138 (delta 7743)

Receiving objects: 100% (10383/10383), 5.04 MiB, done.

Resolving deltas: 100% (7976/7976), completed with 324 local objects.

From git://git.kernel.org/pub/scm/linux/kernel/git/kki_ap/samsung-ap-2.6.git

 * [new branch]      master     -> samsung/master

 * [new tag]         v2.6.28.6-samsung-v1 -> v2.6.28.6-samsung-v1

From git://git.kernel.org/pub/scm/linux/kernel/git/kki_ap/samsung-ap-2.6.git

 * [new tag]         v2.6.28-rc4-s3c64xx -> v2.6.28-rc4-s3c64xx

 * [new tag]         v2.6.28-rc4-s5pc1xx -> v2.6.28-rc4-s5pc1xx

 * [new tag]         v2.6.28-rc5-s3c64xx -> v2.6.28-rc5-s3c64xx

 * [new tag]         v2.6.28-rc5-s5pc1xx -> v2.6.28-rc5-s5pc1xx

 * [new tag]         v2.6.28-rc6-s3c64xx -> v2.6.28-rc6-s3c64xx

 * [new tag]         v2.6.28-rc6-s5pc1xx -> v2.6.28-rc6-s5pc1xx

 * [new tag]         v2.6.28-rc7-s3c64xx -> v2.6.28-rc7-s3c64xx

 * [new tag]         v2.6.28-rc7-s5pc1xx -> v2.6.28-rc7-s5pc1xx

 * [new tag]         v2.6.28-rc8-s3c64xx -> v2.6.28-rc8-s3c64xx

 * [new tag]         v2.6.28-rc8-s5pc1xx -> v2.6.28-rc8-s5pc1xx

 * [new tag]         v2.6.28-rc8-s5pc1xx-v1 -> v2.6.28-rc8-s5pc1xx-v1

 * [new tag]         v2.6.28.6-samsung -> v2.6.28.6-samsung

 

$ git fetch android

remote: Counting objects: 1077412, done.

remote: Compressing objects: 100% (176782/176782), done.

Receiving objects: 100% (1077412/1077412), 263.30 MiB | 28369 KiB/s, done.

remote: Total 1077412 (delta 896526), reused 1076403 (delta 895639)

Resolving deltas: 100% (896526/896526), done.

From git://android.git.kernel.org/kernel/common.git

 * [new branch]      2.6.27     -> android/2.6.27

 * [new branch]      2.6.29     -> android/2.6.29

From git://android.git.kernel.org/kernel/common.git

 * [new tag]         v2.6.12    -> v2.6.12

 * [new tag]         v2.6.12-rc2 -> v2.6.12-rc2

(skipped...)

 * [new tag]         v2.6.29-rc8 -> v2.6.29-rc8

看看有哪些 branches?

$ git branch -a

  android/2.6.27

  android/2.6.29

  samsung/master

在合併之前,先了解一下已存在的 branches。我們可以先看看這些 branches 的共同祖先(common ancestor):

$ git merge-base samsung/master android/2.6.27

3fa8749e584b55f1180411ab1b51117190bac1e5

 

$ git show 3fa8749e584b55f1180411ab1b51117190bac1e5

commit 3fa8749e584b55f1180411ab1b51117190bac1e5

Author: Linus Torvalds

Date:   Thu Oct 9 15:13:53 2008 -0700

 

    Linux 2.6.27

 

diff --git a/Makefile b/Makefile

index ce9eceb..16e3fbb 100644

--- a/Makefile

+++ b/Makefile

@@ -1,7 +1,7 @@

 VERSION = 2

 PATCHLEVEL = 6

 SUBLEVEL = 27

-EXTRAVERSION = -rc9

+EXTRAVERSION =

 NAME = Rotary Wombat

 

 # *DOCUMENTATION*

 

$ git merge-base samsung/master android/2.6.29

4a6908a3a050aacc9c3a2f36b276b46c0629ad91

 

$ git show 4a6908a3a050aacc9c3a2f36b276b46c0629ad91

commit 4a6908a3a050aacc9c3a2f36b276b46c0629ad91

Author: Linus Torvalds

Date:   Wed Dec 24 15:26:37 2008 -0800

 

    Linux 2.6.28

 

    Happy holidays..

 

diff --git a/Makefile b/Makefile

index 4c8d797..71e98e9 100644

--- a/Makefile

+++ b/Makefile

@@ -1,7 +1,7 @@

 VERSION = 2

 PATCHLEVEL = 6

 SUBLEVEL = 28

-EXTRAVERSION = -rc9

+EXTRAVERSION =

 NAME = Erotic Pickled Herring

 

 # *DOCUMENTATION*

因此 branch samsung/master 和 android/2.6.27 都是從 v2.6.27 來的,而 samsung/master 和 android/2.6.29 則從 v2.6.28 而來。事實上,不難驗證 samsung/master 是從 v2.6.28.6 改來的。

可以用 gitk 這個圖形化工具來看看從 v2.6.27 到 android/2.6.27 的變化:

$ gitk v2.6.27..android/2.6.27

同樣的,samsung/master 的變化是:

$ gitk v2.6.28..samsung/master

我們要決定如何進行合併。可以將 samsung 的修改合併到 Android kernel,也可以將 Android 的修改合併到 samsung kernel。我決定選擇後者,因為從 gitk 可以看出 Android 的變化相當簡單而清楚,就是單線發展而已。相對的,samsung kernel 就併來併去,線條亂七八糟,看得眼花瞭亂。因此將 Android 的修改併到 samsung kernel,應該比較簡單而容易成功。

可以用 git rebase 來進行合併。首先,建立一個新的本地 branch 來保存合併結果:

$ git branch --track samsung-android samsung/master

然後用 git rebase 指令,將 v2.6.27 到 android/2.6.27 的修改,一個一個的 apply 到 samsung-android 這個 branch 中:

$ git rebase --whitespace=fix --onto samsung-android v2.6.27 android/2.6.27

First, rewinding head to replay your work on top of it...

Applying: PM: Add wake lock api.

Applying: PM: Add early suspend api.

Applying: PM: Implement wakelock api.

Applying: PM: Implement early suspend api

Applying: PM: Enable early suspend through /sys/power/state

Applying: PM: Add user-space wake lock api.

Applying: PM: wakelock: Abort task freezing if a wake lock is held.

Applying: PM: earlysuspend: Add console switch when user requested sleep state changes.

Applying: PM: earlysuspend: Removing dependence on console.

Applying: rtc: Add android alarm driver.

Applying: rtc: Try to prevent RTC errors from accumulating.

Applying: ledtrig-sleep: Add led trigger for sleep debugging.

error: patch failed: drivers/leds/Makefile:29

error: drivers/leds/Makefile: patch does not apply

Using index info to reconstruct a base tree...

Falling back to patching base and 3-way merge...

Auto-merged drivers/leds/Kconfig

Auto-merged drivers/leds/Makefile

Applying: PM: Wait for console in resume.

Applying: PM: Fix suspend_console/resume_console use only one semaphore.

Applying: switch: switch class and GPIO drivers.

Applying: lowmemorykiller: Initial support for 2.6.27

error: patch failed: drivers/misc/Kconfig:475

error: drivers/misc/Kconfig: patch does not apply

error: patch failed: drivers/misc/Makefile:30

error: drivers/misc/Makefile: patch does not apply

Using index info to reconstruct a base tree...

Falling back to patching base and 3-way merge...

Auto-merged drivers/misc/Kconfig

CONFLICT (content): Merge conflict in drivers/misc/Kconfig

Auto-merged drivers/misc/Makefile

CONFLICT (content): Merge conflict in drivers/misc/Makefile

Failed to merge in the changes.

Patch failed at 0016.

由這些訊息可看出,前 15 個修改被成功的 apply 上去,但第 16 個產生 conflicts。先用 git status 看看問題出在哪裡:

$ git status

drivers/misc/Kconfig: needs merge

drivers/misc/Makefile: needs merge

# Not currently on any branch.

# Changes to be committed:

#   (use "git reset HEAD ..." to unstage)

#

#       new file:   drivers/misc/lowmemorykiller.c

#

# Changed but not updated:

#   (use "git add ..." to update what will be committed)

#

#       unmerged:   drivers/misc/Kconfig

#       unmerged:   drivers/misc/Makefile

#

可以看出有兩個檔案有 conflicts,必須手動修改。例如,在 drivers/misc/Makefile 裡 conflicts 大約在 35 至 39 行:

<<<<<<< HEAD:drivers/misc/Makefile

obj-$(CONFIG_C2PORT)            += c2port/

=======

obj-$(CONFIG_LOW_MEMORY_KILLER) += lowmemorykiller.o

>>>>>>> lowmemorykiller: Initial support for 2.6.27:drivers/misc/Makefile

不難看出,這兩行都要加到 Makefile 中。因此我改成:

obj-$(CONFIG_C2PORT)            += c2port/

obj-$(CONFIG_LOW_MEMORY_KILLER) += lowmemorykiller.o

接著

$ git add drivers/misc/Makefile

用同樣的方法修改 drivers/misc/Kconfig,然後

$ git rebase --continue

如此會繼續合併的過程。當然可能產生其它的 conflicts,都用類似的方法修正,直到 rebase 完成。

如果覺得某個產生 conflicts 的修改是不必要的,可以跳過:

$ git rebase --skip

如果覺得 conflicts 太複雜了,不知要麼修改,想要放棄,可以

$ git rebase --abort

如此會放棄所有的合併結果,而將 source tree 回到合併前的狀態。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值