ソース表示: Git_開発中のGit操作リファレンス #81919

[[PageNavi(Git_Git導入/操作まとめのNavigationList(PageNavi用))]]
ここは、SetucoCMSプロジェクトにおける開発に必要なGitの操作方法をまとめたページです。

= 開発中のGit操作リファレンス
[[PageOutline(start=2, depth=2, type=unordered)]]

== !GitHubからSetucoCMSプロジェクトの最新情報を取得
=== 初めて開発に参加するとき(git clone)
 * 初めてSetucoCMSの開発に加わるときは、まずgit cloneを実行する必要がある
 * SetucoCMSの開発を行うディレクトリを作り、そこに!GitHubからプロジェクトをcloneする
{{{ pre
$ mkdir setucodev
$ cd setucodev
$ git clone ssh://git@ssh.github.com:443/densetubu/SetucoCMS.git .
$ ls SetucoCMS
(正しくcloneされていればSetucoCMSのファイルが表示される)
}}}
 * または、新しいディレクトリでSetucoCMSの開発を始めようと思ったときも、そのディレクトリでgit cloneすればよい
=== 他メンバーの更新内容を取得したいとき(git pull) 
 * 他のメンバーが編集し、!GitHubに反映させた(pushした)内容を取得したいときは、git pull コマンドを実行する
{{{ pre
$ git pull
}}}

 * 指定したリモートブランチを取得したいとき (リモートのiss001ブランチを取得する)
{{{ pre
$ git pull origin iss001:iss001  
}}}

=== git pull時のエラー(変更の競合)
git pullを実行したとき、次のようなエラーが出る場合がある。
{{{ pre
 CONFLICT (add/add): Merge conflict in xxxxx.xxx
 Automatic merge failed; fix conflicts and then commit the result.
}}}
このエラーが表示されたら、自分の編集内容が他のメンバーと競合しているので、該当箇所を手動で編集して、問題を解決しておく。[[BR]]
※そもそもなぜ競合が起きているか、自分が間違った箇所を編集したのではないかなど確認すること

=== git pull時のエラー(未コミット)
ローカルリポジトリでファイルを編集中(未コミット)にgit pullを実行し、編集中のファイルがリモートリポジトリ側でも変更されていた場合、
{{{ pre
$ git pull
*************: needs update
*************: needs update
*************: needs update
...
}}}
{{{ pre
$ git pull
error: Entry '************' not uptodate. Cannot merge.
fatal: merging of trees ************ and *********** failed
}}}
などのエラーが出ることがある。この場合、一旦編集中のファイルをコミットするか、git stashで変更を一時退避、またはgit reset --hardで変更を取り消してからgit pullを実行しなおす必要がある。
== ソースコードを編集するときに必要な操作
=== 編集した内容をコミットの対象にする(git add)
{{{ pre
$ vim index.php  # index.php を編集
$ git add index.php
}}}

=== ステージングを取り消す 
{{{ pre
$ git reset HEAD test.txt
}}}


=== 編集した内容を差分表示して確認する(git diff)
 * ソースコードの編集中に編集内容を確認するには、「git diff」「git diff --cached」「git diff HEAD」の3種類がある
==== 1. 「現在編集中でまだgit add していない内容」と「前回のcommit時の内容」を比較する(git diff)
{{{ pre
$ vim index.php # index.php を編集

$ git diff
diff --git a/index.php b/index.php  # a〜 は編集前、b〜 は編集後を意味する
index 2dad828..01716da 100644
--- a/index.php
+++ b/index.php
@@ -1,5 +1,6 @@
 <?php
 
-phpinfo(); 
-echo 123;
-
+function test () {
+    echo 123;
+    phpinfo();
+}
}}}
 * 行頭に「-」が付いているのが削除(変更)された行で、「+」が付いているのが追加された行
==== 2. 「現在編集中でまだgit add していない内容」と「git add 済みの内容」を比較する(git diff --cached)
{{{ pre
$ vim index.php    # index.php を編集
$ git add index.php   # index.php を git add
$ git diff       # 単なる git diff では何も表示されない(git add していない編集内容がないため)

$ git diff --cached
diff --git a/index.php b/index.php
index 2dad828..01716da 100644
--- a/index.php
+++ b/index.php
@@ -1,5 +1,6 @@
 <?php
 
-phpinfo();
-echo 123;
-
+function test () {
+    echo 123;
+    phpinfo();
+}
}}}
==== 3.  「前回のcommit時から変更があった内容を全て(git addされていてもいなくても)差分表示」する(git diff HEAD)
※「HEAD」とは最新のcommitを指す。
{{{ pre
$ vim index.php   # index.php を編集
$ git add index.php  # ここまでの編集内容をいったん git add
$ vim index.php   # 再度index.php を編集

$ git diff --cached
diff --git a/index.php b/index.php
index e69de29..a73f932 100644
--- a/index.php
+++ b/index.php
@@ -0,0 +1 @@
+this line is 1st edit   # git diff --cached ではgit add された 最初の編集分だけ差分表示される

$ git diff
diff --git a/index.php b/index.php
index e69de29..2ead53d 100644
--- a/index.php
+++ b/index.php
@@ -0,0 +1,2 @@
this line is 1st edit    # git diff では git add された行は「+」も「-」も表示されない
+this line is 2nd edit  # 2回目の編集で入力した行(まだgit addされていない)だけ差分表示される

$ git diff HEAD
diff --git a/index.php b/index.php
index e69de29..2ead53d 100644
--- a/index.php
+++ b/index.php
@@ -0,0 +1,2 @@
+this line is 1st edit  # 1回目の編集で入力した行(既にgit add済み)
+this line is 2nd edit   # 2回目の編集で入力した行(まだgit addされていない) 両方が差分表示される
}}}
=== 状況を確認する(git status)
{{{ pre
$ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#	modified:   index.php
#
no changes added to commit (use "git add" and/or "git commit -a")
}}}
 * 「modified」は「変更されたファイル」の意
 * 「modified」以外に、次のような表示がある
    * 「deleted」:「削除された」
    * 「renamed」:「名前が変更された」
    * 「new file」:「新規作成された」
それ以外の部分の意味を、「#コメント」で書くと以下のとおり。
{{{ pre 
$ git status
# On branch master
# Changes to be committed: # 編集後にgit addされて、次回のcommit対象になっている
#   (use "git reset HEAD <file>..." to unstage)
#
#	modified:   index.php
#
# Changed but not updated: # 編集後まだgit addされておらず、commit対象になっていない
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#	modified:   header.php
#
# Untracked files:      # 作成後まだgit add されておらず、gitの管理対象自体に入っていない
#   (use "git add <file>..." to include in what will be committed)
#
#	newfile
}}}
 * 「Changed but not updated」と「Untracked files」にあるファイルは、いずれもgit add することで『Changes to be committed」に移動する
=== ファイルを削除する(git rm)
 * gitで管理中のファイルを削除したい場合は、git rm コマンドを実行する
{{{ pre
$ git rm index.php
rm 'index.php'
$ git status
# On branch master
# Changes to be committed:   # 次回 commit 時に、ファイルの削除が記録されることが分かる
#   (use "git reset HEAD <file>..." to unstage)
#
#	deleted:    index.php 
#
}}}
 * もし単なる rm コマンドや、GUI操作でファイルを削除した場合は、後からでも git rm コマンドを実行すればよい
{{{ pre
$ rm index.php
$ git status
# On branch master
# Changed but not updated:   # 次回 commit 時の対象になっていない
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#	deleted:    index.php
#
no changes added to commit (use "git add" and/or "git commit -a")
$ git rm index.php
rm 'index.php'
$ git status
# On branch master
# Changes to be committed:   # 次回 commit 時の記録対象になった
#   (use "git reset HEAD <file>..." to unstage)
#
#	deleted:    index.php 
#
}}}
=== ファイルの名前を変更する/ファイルを移動する(git mv)
 * ファイル名を変更する場合、「git mv 変更前のファイル名 変更後のファイル名」を実行する
 * または、ファイルを移動する場合、「git mv 移動させるファイル 移動先」を実行する
{{{ pre
$ git mv index.php page.php
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	renamed:    index.php -> page.php
#
}}}
 * この後 commit すれば、ファイル名の変更がgit に記録され、元index.php であったことや、そのときの変更履歴が page.php に引き継がれる
 * 単なる mv コマンドやGUI操作でファイル名を変更してしまうと、「元のファイルの削除」と「新規ファイルの追加」として扱われてしまうため注意
=== コミットする(git commit)
 * 事前に編集した内容を git add していないとエラーになる
{{{ pre
$ git commit
}}}
 * 実行すると、git config --global core.editorで設定したエディタが起動し、コミットメッセージの入力を求められる
==== コミットメッセージの書き方(1行目(必須)は編集理由と内容の要約、3行目(オプション)以降に補足説明)
 * コミットメッセージを書くときは、以下の形式を守って書くこと。
{{{ pre
 1.  コミットの理由と内容(1行かつ50文字以内。)
 2.
 3.  詳細なコミットの内容や変更した理由(行数、文字数の制限はない。)
 4.  〜(詳細な記述の続き)〜
 5.  〜(さらに続き)〜・・・
}}}
 1. 1行目はコミットの'''理由'''と内容(1行かつ50文字以内)
 1. 2行目は空行
 1. 3行目以降は、1行目だけで書ききれなかった場合に、変更の理由と内容を詳細に補足して書く(行数、文字数制限なし)
1行目だけで理由と編集内容が表現しきれれば3行目以降は不要だが、できるだけ面倒くさがらずに「なぜ」「何をしたか」を書くこと。

=== 編集後、誤ってコミットしてしまったとき、コミットを取り消す(git reset (--soft) HEAD^)
各ファイルの内容はコミットしたときのまま、「コミットしたこと」だけを取り消すことができる。
{{{ pre
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	modified:   index.php
#
$ git commit                                     # 誤ってコミットしてしまった
$ git reset --soft HEAD^                         # コミットだけを取り消す
index.php: locally modified
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	modified:   index.php                    # git commit前、git add済みの状態に戻る
#
}}}
上の例では、index.phpを編集した後に誤ってコミットしてしまったが、コミットだけを取り消し、index.phpは引き続き編集することができるようになっている。

なお、「--soft」を省略しても、同様に編集内容を残してコミットだけを取り消すことができるが、その場合は「git add」もされていない状態に戻る。
{{{ pre
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	modified:   index.php
#
$ git commit                                     # 誤ってコミットしてしまった
$ git reset HEAD^                                # コミットだけを取り消す
index.php: locally modified
$ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#	modified:   index.php                    # git commit前、git add前の状態に戻る
#
}}}
=== コミットしてしまったあとで、一つ前のコミット時の内容に戻す(git revert)
 * git revertコマンドを実行すると、コミットしたのと'''逆の編集内容を持つ新しいコミットを作る'''ことができる
 * 結果的に、ソースコードを一つ前のコミット時の状態に戻すことができる
{{{ pre
$ git revert HEAD
}}}
 * 実行すると、コミットメッセージの編集が求められる。コミットメッセージは、最初から次のように入力されている
{{{ pre
 1. Revert "前回のコミット要約"
 2. 
 3. This reverts commit 前回のコミットハッシュ値
 4.
 5. # Please enter ...
}}}
 * 最初から入力されている1行目と3行目はそのままにすること
 * 4行目以降を使って、revertを行った理由を詳細に記載すること(行数、文字数の制限はない。以下、例)
{{{ pre
 1. Revert "前回のコミット要約"
 2. 
 3. This reverts commit 前回のコミットハッシュ値
 4. index.phpを間違えてコミットしてしまったため、git revert実行。
 5. 誤)<?= $path ?> 正)<?php echo $path ?>
 7. この後、正のように編集しなおしてコミットしなおす予定。
 8. # Please enter ...
}}}

=== 編集している内容を破棄して、最新のコミットの状態に戻る(git reset --hard)
 * 最新のコミットの状態に戻り、そのあとに加えた変更が一切失われる
 * git reset --hard は基本的に取り消せないので注意

{{{ pre
$ git reset --hard
}}}

 * 過去のコミットを削除することも出来てしまうが、リポジトリを壊す要因になるので'''禁止'''

=== ブランチを使って作業する(git branch/git checkout)
みんなで使っているmasterブランチには変更を加えず、実験的にソースコードに変更を加えられる。
==== ブランチを作る(git branch)
 * 現在のブランチ(何もいじっていなければmasterブランチ)と同じ内容のsampleブランチを作る
{{{ pre
$ git branch sample
}}}
==== ブランチを切り替える(git checkout)
 * 現在居るブランチと、存在するブランチをgit branchコマンドで確かめる
{{{ pre
$ git branch
* master
  sample
}}}
 *「*」がついているmasterブランチが現在の作業場所
 * masterブランチからsampleブランチに作業場所を切り替える(移動する)
{{{ pre
$ git checkout sample
$ git branch
  master
* sample
}}}
sampleブランチに移動した。
==== 他のブランチで行った編集作業をmasterブランチに反映する(git merge)
 * sampleブランチで編集を行い、正しく動作することを確認しコミットしたら、sampleブランチでの編集内容をmasterブランチに反映させる。
{{{ pre
$ git checkout master  # まず、反映先のブランチ(=master)に移動
$ git branch  # 現在のブランチの状況を確認
* master
  sample
$ git merge sample  # sampleブランチをmasterブランチにマージ
}}}
sampleブランチで行った編集内容が反映されていることを確かめておく。
====  用済みのsampleブランチを削除する(git branch -d)
{{{ pre
$ git branch -d sample
}}}
=== 過去の時点を取り出す(git checkout ''戻りたい時点'')
 * git log コマンドなどで、戻りたい時点のコミットハッシュ値を調べる
{{{ pre
$ git glog
* xxxxxxx <AkihiroTSUKADA> - (HEAD, master) Revert "index.phpにコメントを追加" (6 minutes ago)
* yyyyyyyy <AkihiroTSUKADA> - index.phpにコメントを追加 (46 minutes ago)
* zzzzzzz <AkihiroTSUKADA> - index.phpを作成 (58 minutes ago)
}}}
(git glogコマンドについては[http://sourceforge.jp/projects/setucocms/wiki/Git_Git%E5%B0%8E%E5%85%A5%E3%80%9C%E5%90%84%E7%A8%AE%E8%A8%AD%E5%AE%9A#h3-.E3.82.A8.E3.82.A4.E3.83.AA.E3.82.A2.E3.82.B9.EF.BC.88.E3.82.B3.E3.83.9E.E3.83.B3.E3.83.89.E3.81.AE.E3.82.B7.E3.83.A7.E3.83.BC.E3.83.88.E3.82.AB.E3.83.83.E3.83.88.EF.BC.89.E3.81.AE.E7.99.BB.E9.8C.B2 Git導入〜各種設定>エイリアス(コマンドのショートカット)の登録] を参照)
 * 例えば、58分前の「index.phpを作成」の時点に戻りたいなら、次のコマンドを実行する。
{{{ pre
$ git checkout zzzzzzz
}}}
 * ディレクトリの状態がその時点に戻り、次のメッセージが表示される
{{{ pre
Note: checking out 'zzzzzzz'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

HEAD is now at zzzzzzz... index.phpを作成
}}}
 * このとき、一時的に無名のブランチが作られ、そこで作業しているような状態になる
{{{ pre
$ git branch
* (no branch)
  master
}}}
==== 過去の時点の確認を終え、最新の時点に戻る(git checkout master)
 * git checkoutコマンドでmasterブランチに移動する
{{{ pre
$ git checkout master
}}}
これで、任意の時点のディレクトリ内容を確認し、最新の時点に再度戻ってくることができる。
==== ファイルを間違えて編集してしまったので、直前の状態に戻す
 * git checkout HEAD -- $file で指定したファイル名を最後にコミットしたものに変更する

{{{ pre
$ git checkout HEAD -- test_file.txt
}}}
text_file.txtが最後にコミットした状態に置き換わる

== !GitHubのSetucoCMSプロジェクトに編集内容を反映させる(git push)
 * ある程度まとまった単位での編集、コミットが完了したら、変更を!GitHubに反映させる
{{{ pre
$ git push origin master
}}}
=== pushしようとしたらエラーが出たとき
 * 自分が編集している間に他のメンバーがpush したためにリポジトリの内容が更新されているときは、次のエラーが出ることがある
{{{ pre
$ git push origin master
To ssh://git@ssh.github.com:443/densetubu/SetucoCMS.git
! [rejected] master-> master(non-fast forward)
error: failed to push some refs to 'ssh://git@ssh.github.com:443/densetubu/SetucoCMS.git'
}}}
 * このときは、一旦git pullコマンドで最新のリポジトリ情報を取得してから、再度pushを試みる
{{{ pre
$ git pull
$ git push origin master
}}}
このときgit pullでエラーが出やすいが、そのときは[#h3-git.20pull.E6.99.82.E3.81.AE.E3.82.A8.E3.83.A9.E3.83.BC.EF.BC.88.E5.A4.89.E6.9B.B4.E3.81.AE.E7.AB.B6.E5.90.88.EF.BC.89 git pull時のエラー]を参照のこと。

[[PageNavi(Git_Git導入/操作まとめのNavigationList(PageNavi用))]]