Edited at

Gitで部分的にコミットする方法

More than 3 years have passed since last update.

一つのファイルの中にたくさん変更を行ったんだけど、コミットする単位は小分けにしたいというケースがあります。

そんな時は、git add -pすると良いようです。試してみましょう。

$ git add -p app/models/blog.rb

diff --git a/app/models/blog.rb b/app/models/blog.rb
index 17bb72a..88634db 100644
--- a/app/models/blog.rb
+++ b/app/models/blog.rb
@@ -1,7 +1,10 @@
# coding: utf-8
-
require_relative 'post'

+module Conversions
+
+end
+
class Blog
attr_writer :post_source

Stage this hunk [y,n,q,a,d,/,j,J,g,s,e,?]?

差分があるところが切りだされて、「ここはStagingに乗せる?」と聞いてきます。

Stagingに乗せる場合は、「y」と答えます。そうでない場合は「n」と答えます。

今回は、「n」と答えます。すると、次の差分が出てきます。

@@ -35,12 +38,29 @@ class Blog

fetch_entries
end

+ def tags
+ Post.all_tags_alphabetical
+ #entries.all_tags_alphabetical
+ end

def filter_by_tag(tag)
FilteredBlog.new(self, tag)
end

private
+ class FilteredBlog < DelegateClass(Blog)
+ include ::Conversions
+
+ def initialize(blog, tag)
+ super(blog)
+ @tag = tag
+ end
+
+ def entries
+ Taggable(super).tagged(@tag)
+ end
+ end
+
def post_source
@post_source ||= Post.public_method(:new)
end
Stage this hunk [y,n,q,a,d,/,K,g,s,e,?]?

出てきた差分のうち、class FilteredBlog < DelegateClass(Blog)の部分だけをStagingに乗せようと思います。

そこで「e」を押すと、エディタが表示されます。

スクリーンショット 2014-04-18 22.42.50.png

私の環境ではVimが表示され、先ほどの差分が表示されました。更に最後までスクロールすると、次のように書かれています。

 # ---

# To remove '-' lines, make them ' ' lines (context).
# To remove '+' lines, delete them.
# Lines starting with # will be removed.
#
# If the patch applies cleanly, the edited hunk will immediately be
# marked for staging. If it does not apply cleanly, you will be given
# an opportunity to edit again. If all lines of the hunk are removed,
# then the edit is aborted and the hunk is left unchanged.

英語で書かれていますが、まとめると、


  • '-'の行をaddしたくなければ、'-'を' '(空白)にする。

  • '+'の行をaddしたくなければ、'+'の行を消す。

  • 先頭に#と書かれている行はaddされません。

ということです。

今回の例では、次のようにすればOKです。

スクリーンショット 2014-04-18 22.48.16.png

def tagsからendまでの行を単純に削除しました。これを保存します。

git statusとすると、同じファイルなのにStagingにいるものとStagingに居ないものとに分かれています。

$ git status                                                   

On branch master
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)

Changes to be committed:
(use "git reset HEAD <file>..." to unstage)

modified: app/models/blog.rb

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: app/models/blog.rb

$

更に確認がしたい場合は、git diff --cachedでStaging環境にあるものの差分が、git diffでStaging環境にないものの差分が確認できますので、コミットする前に確認してもよいでしょう。

後は普通にgit commitでコミットすればOKです。