Git add -p 로 수정사항 분리하기
git commit 은 하나의 수정 사항을 반영 하는 것이 Kernel 과 같은 대형 project 에 merge 될 확률이 높다. 이는 kernel에 Documentation/SumittingPatches 의 3번(Separate your changes.)의 내용을 보면 알 수 있다.
하지만 수정을 하다 보면, 하나의 commit 내부에 두 개 이상의 bug 수정이 있을 수 있다. 이런 경우 여러 개의 Commit 으로 분리하는 방법을 작성해 본다.
최근 Kernel patch 를 만드는 과정에서 Maintainer 가 두 개로 분리해달라는 요청이 있었고, 이를 위해 고민하다 검색으로 찾아낸 방법이다.
이미 하나의 commit 으로 내 local branch 에 있다. 이 commit 을 두 개로 분리했던 과정을 살펴본다.
1. 내 commit 이전으로 돌아간다.
- 이 때, 분리하려는 commit 이 최상위에 있어야 한다. 만약 최상위가 아니라면 http://woodz.tistory.com/75 여기를 참고하시면 된다.
이렇게 하면, 최상위에서 바로 전의 commit 으로 reset 이 되고 내 수정 사항은 un-stage 된다.
현재 상황은, 아래와 같다. 아래서 위쪽 code block 과 아래쪽을 분리하여 commit 할 것이다.
$ git diff
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 0ee63af..0679854 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -4087,10 +4087,7 @@ static void wq_update_unbound_numa(struct workqueue_struct *wq, int cpu,
if (cpumask_equal(cpumask, pwq->pool->attrs->cpumask))
goto out_unlock;
} else {
- if (pwq == wq->dfl_pwq)
- goto out_unlock;
- else
- goto use_dfl_pwq;
+ goto use_dfl_pwq;
}
mutex_unlock(&wq->mutex);
@@ -4100,7 +4097,8 @@ static void wq_update_unbound_numa(struct workqueue_struct *wq, int cpu,
if (!pwq) {
pr_warning("workqueue: allocation failed while updating NUMA affinity of \"%s\"\n",
wq->name);
- goto out_unlock;
+ mutex_lock(&wq->mutex);
+ goto use_dfl_pwq;
}
/*
이 상태에서 "git add -p" 를 입력하면,
$ git add -p
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 0ee63af..0679854 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -4087,10 +4087,7 @@ static void wq_update_unbound_numa(struct workqueue_struct *wq, int cpu,
if (cpumask_equal(cpumask, pwq->pool->attrs->cpumask))
goto out_unlock;
} else {
- if (pwq == wq->dfl_pwq)
- goto out_unlock;
- else
- goto use_dfl_pwq;
+ goto use_dfl_pwq;
}
mutex_unlock(&wq->mutex);
Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]? n
알아서 한 블럭씩 분리하여 더 나눌 것인지, 아니면 이부분을 하나의 Commit 으로 만들 것인지 물어본다.
나는 아래의 block 을 먼저 commit 하고 이 부분을 나중에 commit 하려고 한다. 그래서 "n" 을 입력했다.
n 을 입력하면,
@@ -4100,7 +4097,8 @@ static void wq_update_unbound_numa(struct workqueue_struct *wq, int cpu,
if (!pwq) {
pr_warning("workqueue: allocation failed while updating NUMA affinity of \"%s\"\n",
wq->name);
- goto out_unlock;
+ mutex_lock(&wq->mutex);
+ goto use_dfl_pwq;
}
/*
Stage this hunk [y,n,q,a,d,/,K,g,e,?]? y
다음 block 의 code를 할 것인지 연속적으로 물어본다. 여기서 "y" 를 입력하면 이 부분만 git add 가 된다.
확인을 해보면,
$ git status
# Not currently on any branch.
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: kernel/workqueue.c
#
# 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: kernel/workqueue.c
#
위에서 처럼 일부는 add 가 되고 나머지는 un-stage 상태가 된다.
그 다음에
$ git commit -s
제목 쓰고.. 내용 쓰고.. 저장 하고 나온다.
또 그 다음에 나머지 수정 사항을 기록 한다.
$ git add
$ git commit -s
제목 쓰고.. 내용 쓰고.. 저장하고 나온다.
그렇게 하면 의도했던 대로 하나였던 commit 이 두 개로 분리가 된다.
사실 이렇게 하지 않아도 되는데, 지저분하거나 혹은 새로 작성해야 하는 문제가 발생한다. 물론 위와 같은 예제는 간단해서 다시 작성해도 되긴 하지만, 이와 같은 방법을 사용하면 이미 잘 작성된 code 에 실수 등이 발생하지 않을 것이다.(code는 건들지도 않으니.. 물론 분리를 잘못하면 발생하는 문제는 있긴 하다. :-) )
이렇게 해서 patch 를 보내면 된다.