11 Mar 2010

Git入門 ゼロから始めるGitドリル

gitSVNsvn使

svngitLinuxgithubgitfarmGit Hosting









Git













--hard--soft











 - 







 - 2 + 

github使

Git + Apache + Basic






OS
Mac
Ubuntu
Windows




Git


$ mkdir ~/workspace/git
$ cd  ~/workspace/git

# 初期化
$ git init
$ ls .git
branches  config  description  HEAD  hooks  info  objects  refs
$ echo trial > test.txt

# 索引の追加
# 索引はコミットする前のステージのようなもの。
# 索引はgit add によって繰り返し更新可能
# git add .はカレントディレクトリ以下のディレクトリ/ファイルを再帰的にスナップショットに追加します
$ git add .
# 削除したファイルを索引に追加する場合は -uが必要。例, git add -u path/to/files/no/longer/necessary 

# メッセージを指定してコミット
$ git commit -m "initial commitment"

# ブランチの一覧を表示
$ git branch
* master #=> masterというブランチは初期状態で作成されます
$ git log
commit e1bf45812b9eedb8aa578af3c0e87a96d84cf3b6
Author: bob 
Date:   Fri Mar 12 00:28:59 2010 +0000

initial commitment



git
$ mkdir trial
$ mv test.txt trial/
$ mv .git trial/
$ cd trial

# gitが動作している事を確認
$ git show #最後のコミット情報が表示される


subversionpush()

logtag使Gitsubversion使




$ git branch new 
$ git branch
*  master #=> *は現在どのブランチを参照しているかを示しています
new

# svnのcheckoutはリポジトリから最新を取得しますが、
# gitのcheckoutはブランチを切り替えてその最新を取得します。
$ git checkout new
Switched to branch 'new'
$ git branch
master
* new
$ git checkout master

# ブランチの削除
$ git branch -d new


(2)
# 新しくブランチを作成してチェックアウトします。= git branch new + git checkout new
$ git checkout -b new
$ echo ' of git' >> test.txt

# 変更をリポジトリに報告
$ git add .

# 索引と最後のコミットを比較
$ git diff --cached
diff --git a/test.txt b/test.txt
index 10b4e1b..48215e2 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1,2 @@
trial
+ of git

# 今どんな状態?
$ git status
# On branch new # newブランチ上に
# Changes to be committed: # コミットすべき変更有り 
#   (use "git reset HEAD ..." to unstage)
#
# modified:   test.txt #更新: test.txt
#
$ cat .git/COMMIT_EDITMSG 
modified test.txt
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch new
# Changes to be committed:
#   (use "git reset HEAD ..." to unstage)
#
# modified:   test.txt
#

# -mオプションを省略するとgit diffと同様に
# commitによってどのような変更がなされるか#付きのコメント行で示される。
$ git commit
modified test.txt
# On branch new 
# Changes to be committed: 
#   (use "git reset HEAD ..." to unstage) #unstage(索引を空に)したい場合はgit rest HEADしてね
#
# modified:   test.txt 
#

svnbranch
git

.git/HEAD
$ cat .git/HEAD
ref: refs/heads/new
$ cat .git/refs/heads/new
bdfb3c51bba2c6d60e7bc326ea686702849c21ab
$ git show
commit bdfb3c51bba2c6d60e7bc326ea686702849c21ab
$ cat test.txt
trial
of git
$ git checkout master
$ cat .git/HEAD
ref: refs/heads/master
$ cat test.txt
trial

# 作業ディレクトリにnewブランチの変更を引き込む
$ git pull . new
$ cat test.txt 
trial
of git
$ gitk





$ git tag v0.10.00

# タグの一覧表示
$ git tag -l
v0.10.00
vx.xx.xx
:
vx.xx.xx
# タグはいろんな箇所で使えます
$ git diff v0.10.00 ORIG_HEAD
# v0.10.0の位置に "stable" という名前の新しいブランチを作成
$ git branch stable v0.10.00 





$ mkdir bin
$ touch bin/gabage
$ git status
# On branch master
# Untracked files:
#   (use "git add ..." to include in what will be committed)
#
# bin/ => binが追跡されてないのでgit addして と言ってる
nothing added to commit but untracked files present (use "git add" to track)

$ vi .gitignore
bin/*                                                                               */  
$ git status
# On branch master
# Untracked files:
#   (use "git add ..." to include in what will be committed)
#
# .gitignore => .gitignoreもgitの管理対象
nothing added to commit but untracked files present (use "git add" to track)

$ git add .gitignore
$ git commit
Added new file .gitignore           
$ git status
# On branch master
nothing to commit (working directory clean)




 - Git1 git "" 使 "" 使 使

 - git (index) 

[HEAD]

 git commit

[index]

 git add

[working tree]

$ echo 1 > diff.txt
$ git add diff.txt
$ echo 2 > diff.txt

# 索引 と 最後のコミットを比較
$ git diff --cached
diff --git a/diff.txt b/diff.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/diff.txt
@@ -0,0 +1 @@
+1

# 作業ディレクトリ と 索引 を比較
$ git diff
diff --git a/diff.txt b/diff.txt
index d00491f..0cfbf08 100644
--- a/diff.txt
+++ b/diff.txt
@@ -1 +1 @@
-1
+2

# 作業ディレクトリ と 最後のコミット を比較
$ git diff HEAD
diff --git a/diff.txt b/diff.txt
new file mode 100644
index 0000000..0cfbf08
--- /dev/null
+++ b/diff.txt
@@ -0,0 +1 @@
+2






SVN

- 
git reset -- filename

- 
git reset --hard HEAD

- 
git reset --hard ORIG_HEAD

- 
git revert HEAD

 --hard--hard--soft

--hard--soft


$ git reset -h
--mixed reset HEAD and index                
--soft  reset only HEAD                     
--hard  reset HEAD, index and working tree 
--merge reset HEAD, index and working tree


使git checkout filenamegit reset --hard '--'
$ git checkout -- filename




$ git status
# On branch master
# Changed but not updated:
#   (use "git add/rm ..." to update what will be committed)
#   (use "git checkout -- ..." to discard changes in working directory)
#
# deleted:    rerun.txt

$ git checkout -- rerun.txt
$ ls
rerun.txt


$ touch abigmistake
$ git add .
$ git commit -m 'a big mistake'
$ git log
commit b37c941bfe9364b681c8b760397b14e846b8fc7d
Author: suzukimilanpaak 
Date:   Fri Mar 19 17:05:55 2010 +0000

a big mistake

commit bdfb3c51bba2c6d60e7bc326ea686702849c21ab
Author: bob 
Date:   Fri Mar 12 01:08:36 2010 +0000

modified test.txt

$ git reset --hard ORIG_HEAD

# 以下のように特定のタグを指定することもできる
$ git reset --hard v0.10.00

#注意!: 作業ディレクトリの変更も削除されてしまう
$ ls
bin test.txt

$ git log
commit bdfb3c51bba2c6d60e7bc326ea686702849c21ab
Author: bob 
Date:   Fri Mar 12 01:08:36 2010 +0000

modified test.txt

commit e1bf45812b9eedb8aa578af3c0e87a96d84cf3b6
Author: bob 
Date:   Fri Mar 12 00:28:59 2010 +0000

initial commitment


! git reset --hard ORIG_HEADHEAD 'a big mistake'git reset --hard ORIG_HEAD



$ git reset --soft HEAD^

便




 git revert 

$ echo foo > test.txt
$ git commit -am 'Modified test.txt'
# HEADをORIG_HEADの内容に戻す。コミットも同時に行われます
$ git revert HEAD

Revert "Modified test.txt"

This reverts commit 07abe15e79f4c1429fb1d22247723e29dc50293a.

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
#   (use "git reset HEAD ..." to unstage)
#
#       modified:   test.txt
#

$ git log
commit 42b30ec986d7fdb8d76c7a5b7c89f17114e8039c
Author: bob 
Date:   Fri Mar 12 01:45:28 2010 +0000

Revert "Modified test.txt"

This reverts commit 07abe15e79f4c1429fb1d22247723e29dc50293a.

commit 07abe15e79f4c1429fb1d22247723e29dc50293a
Author: bob 
Date:   Fri Mar 12 01:45:04 2010 +0000

Modified test.txt

#ここまでの変更をGUIで表示
$ gitk &


 - git reset HEAD 



$ touch abigmistake
$ git add .
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD ..." to unstage) #unstageする場合はgit reset HEADしてね
#
# new file:   abigmistake
#
$ git reset HEAD abigmistake

# 索引から履歴は削除されるがファイル自体は残っている
$ ls
abigmistake  test.txt

# もう一度索引に追加することもできます
$ git add abigmistake

$ git reset --hard HEAD
$ ls
test.txt


 - 




# aliceの署名情報を設定
$ git config --global user.name "alice"
$ git config --global user.email "engineerflies+alice@gmail.com"
$ cat ~/.gitconfig
[user]
name = alice
email = engineerflies+alice@gmail.com
$ cd ..
$ mkdir alice && mv trial alice
$ git clone ./alice bob
bob$ cd bob
# bobの署名情報を設定(この場合同じユーザで書名情報を設定しているので~/.configを上書きする)
bob$ git config --global user.name "bob"
bob$ git config --global user.email "engineerflies+bob@gmail.com"

bob$ echo bob edited >test.txt
bob$ git commit -am "bob edited"
alice$ echo alice edited > test.txt
alice$ git add .

# bobのmasterブランチを現在のaliceのmasterブランチに取り寄せる
# 変更情報のみがリモート追跡用ブランチに格納されます。test.txtは変更されない
alice$ git fetch ../bob master
alice$ cat test.txt 
alice edited

# aliceのHEADとbobからpullしたFETCH_HEADの差異を表示
alice$ git diff HEAD..FETCH_HEAD
diff --git a/test.txt b/test.txt
index 48215e2..4cba843 100644
--- a/test.txt
+++ b/test.txt
@@ -1,2 +1 @@
-trial
- of git
+bob edited
alice$ cat .git/FETCH_HEAD 
b61671548ad431d9d865f0dd7eaeded68ec23711  branch 'master' of ../bob
alice$ git merge FETCH_HEAD
Updating 7d62c24..b616715
error: Entry 'test.txt' would be overwritten by merge. Cannot merge.

#このコミットはコンフリクトを起こさない(HEADと作業ディレクトリを比較しているから?)
alice$ git commit -am "alice edited"
alice$ git log
commit d04f56226dde3ac67839a5695ab6fb5644a34bc9
Author: bob 
Date:   Thu Mar 18 13:21:13 2010 +0000

alice edited

commit 7d62c24953010a7628b29e891405e973b24a4239
Author: bob 
Date:   Fri Mar 12 01:44:29 2010 +0000

ignore bin/
:
:

# 再度merge - コンフリクトを起こします
alice$ git merge FETCH_HEAD
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
Automatic merge failed; fix conflicts and then commit the result.
このようにマージは常に直前にコミットが済んでいることを想定して行われる様です。
dirtyな状態(現在のブランチにコミットされていない変更が作業ディレクトリ内に含まれていること)ではマージは行われません。

#コンフリクトを手動で回収します
alice$ vi test.txt
bob edited then alice edited

結果の表示
# bobが最後にpullしてから、aliceがbobの変更をpullするまでの変更を表示する
$ gitk HEAD..FETCH_HEAD
# aliceとbobのそれぞれの変更のうちお互いに'到達不可能な'変更を表示する
$ gitk HEAD...FETCH_HEAD

alice$ git commit -a
Merge branch 'master' of ../bob #マージ用のログを自動生成してくれます

Conflicts: #コンフリクトが test.txtにあった
test.txt
#
#あなたはマージをコミットしている様です(とgitは認識しています)
# It looks like you may be committing a MERGE. 
#これが正しくなかったら、.git/MERGE_HEADを削除してからもう一回トライしてね
# If this is not correct, please remove the file 
#       .git/MERGE_HEAD
# and try again.
#

#以下はいつもコミット時に表示されるメッセージと同じ
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
#   (use "git reset HEAD ..." to unstage)
#
#       modified:   test.txt
#

#最後にaliceの変更をbobにも取り寄せておきます
#pull は fetch + mergeと等価です
bob$ git pull ../alice master




bob$ echo love letter from canada >> testto.txt 
bob$ git commit -am "love letter"
alice$ echo affair in us>>test.txt 
alice$ git pull ../bob
# stash: 隠しもの
alice$ git stash save affair
# 隠しものを一覧する
alice$ git stash list
stash@{0}: On master: affair
alice$ git pull ../bob
alice$ vi test.txt 
love letter from canada
love letter from us
alice$ git commit -am "in love"
alice$ git stash clear




alicegit pull ../bobbobbobalicebobalicebob便
bob$ echo bob edited > test.txt 
bob$ git commit -am "bob eidted"
alice$ git remote add bob ~/workspace/git/bob
alice$ git branch -r
bob/master
alice$ cat .git/config 
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "bob"]
url = /home/suzukimilanpaak/workspace/git/bob
fetch = +refs/heads/*:refs/remotes/bob/*                             


# 変更情報のみがリモート追跡用ブランチに格納されます。test.txtは変更されない */
alice$ git fetch bob

# 自分のmasterとbobのmasterを比較
# -p はpatchの略、patch提出用のログメッセージを出力してくれます
alice$ git log -p master..bob/master
commit 460f2c8928b7f1b1065766c6c2652f79001a054c
Author: bob 
Date:   Thu Mar 18 14:01:11 2010 +0000

bob eidted

# -pによって出力される変更ログ
diff --git a/test.txt b/test.txt
index 843ad85..4cba843 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1 @@
-love letter from canada
+bob edited
alice$ git merge master bob/master
Already up-to-date with ed79b27cc53885e29b2770a9f20d8fb2174e48b6
Trying simple merge with 460f2c8928b7f1b1065766c6c2652f79001a054c
Simple merge did not work, trying automatic merge.
Auto-merging test.txt
ERROR: content conflict in test.txt 
fatal: merge program failed
Automatic merge failed; fix conflicts and then commit the result.

# コンフリクトを解消します
alice$ vi test.txt
love letter from canada
love letter from us
bob edited
alice$ git commit -a
Merge branch 'master'; commit 'bob/master'

Conflicts:
test.txt

# bobのリポジトリはaliceをcloneして作られたためoriginにaliceのリポジトリが指定されている。
bob$ cat .git/config 
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*                                          */
url = /home/suzukimilanpaak/workspace/git/./alice
[branch "master"]
remote = origin
merge = refs/heads/master
bob$ git config -l
user.name=bob
user.email=sin.wave808+bob@gmail.com
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*                             */
remote.origin.url=/home/suzukimilanpaak/workspace/git/./alice
branch.master.remote=origin
branch.master.merge=refs/heads/master
bob$ git branch -r
origin/HEAD -> origin/master
origin/master
origin/new

# git pullで引数を省略すると remote "origin"に登録されている変更を取り寄せる
bob$ git pull

# ちゃんと変更されてる
bob$ cat test.txt 
love letter from canada
love letter from us
bob edited





便

$ git log
commit 74f846a1bde25ef729b1742bfcd9fc693da1dbda

# ある時点のコミットの詳細を表示
# SHA1値の全てを指定する必要は無い
$ git show 74f846a1bde25ef
commit 74f846a1bde25ef729b1742bfcd9fc693da1dbda
Merge: 17b2308 a01e7b7
Author: suzukimilanpaak 
Date:   Fri Mar 5 17:25:15 2010 +0000

tip of collaboration


$ git show HEAD^  # HEAD の親を表示
$ git show HEAD^^ # HEAD の祖父を表示
$ git show HEAD~4 # HEAD の4つ前を表示

# "love"を検索
$ git grep love
test.txt:love letter from canada
test.txt:love letter from us

# "love"をタグv0.00.00から検索
$ git grep love v0.10.00 #=> 何も見つからない
$ git log v0.10.00              # v0.10.00以降のコミット
$ git log --since=yesterday     # 昨日からのコミット
$ git log --since="3 hours ago" # 3時間前からのコミット

# 最近2週間に "drivers" ディレクトリを修正したコミットでgitkで表示
$ gitk --since="2 weeks ago" drivers/ 

# ファイル名を指定
$ git diff v0.10.00:test.txt HEAD:test.txt

# 変更したファイル名を検索
$ git log --stat|grep -A 5 haml
changed the view rendering engine html to haml.

app/views/feeds/new.html.haml |   48 ++++++++++++++++------------------------
1 files changed, 19 insertions(+), 29 deletions(-)




$ git checkout -b a
$ echo a > a.txt
$ git commit -am "a"

# aにあってmasterにないコミットを表示
$ git log master..a
commit b090846acd519c2066a8975ed4c76de700d66fc3
Author: bob 
Date:   Thu Mar 18 14:44:04 2010 +0000

a

#masterにあってaにないコミットを表示 => 何も表示されない
$ git log a..master



 - 2 + 


bobaliceorigin

/opt$ mkdir git

# rootというリポジトリをaliceからコピーして生成します。
# この作業の前にaliceが開発の先端になっているべきであることに注意してください。
# bare"裸の"とは作業ファイルがなく、管理情報だけを持つリポジトリという意味
# sharedを付けると共用のユーザ権限がリポジトリに与えられます
/opt$ git clone --bare --shared ~/workspace/git/alice/ root
alice$ git remote rm bob

# -t: master ブランチをtrack"追跡"します
alice$ git remote add -t master origin /opt/git/root
alice$ git config -l
remote.origin.url=/opt/git/root
remote.origin.fetch=+refs/heads/master:refs/remotes/origin/master
# fetchがrefs/heads/masterを参照する様に設定されています
# -tオプションが指定されていない場合はrefs/heads/*が設定されます */

# 引数なしでpullをするとremotes/origin/masterから変更を取り寄せます
# git remote add に-tを使用したためです。
alice$ git pull

# これまでこの記事にそってリポジトリを作成してきた場合originはaliceを参照しているはずです
bob$ git config -l
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*                                 */
remote.origin.url=/home/suzukimilanpaak/workspace/git/./alice
bob$ git remote rm origin
bob$ git remote add -t master origin /opt/git/root
bob$ git pull


bob$ echo love from vancouver > test.txt
bob$ git commit -am "love from vancouver"
bob$ sudo git push origin master

alice$ echo love from san francisco > test.txt 
alice$ git commit -am "love from san francisco"
alice$ sudo git push origin master
To /opt/git/root
! [rejected]        master -> master (non-fast forward) 
error: failed to push some refs to '/opt/git/root'


fast forwardpush
fast forward - gitfast forward

alicebobfast forwardpush

alice$ git pull
CONFLICT (content): Merge conflict in test.txt
alice$ vi test.txt
love from vancouver
love from san francisco
alice$ git commit -a
alice$ git push origin master

push

root$ git log
commit 40c4ded3df30d696a16552d928b3a46515cfb516
Merge: f180d66 a2bcc0d
Author: bob 
Date:   Thu Mar 18 17:00:51 2010 +0000

Merge branch 'master' of /opt/git/root

Conflicts:
test.txt

commit f180d664d2943ccc83075e7dc1300f7dca999d72
Author: bob 
Date:   Thu Mar 18 16:40:37 2010 +0000

love from san francisco

commit a2bcc0d98f0e2c98d37df233aecb30caacb028f5
Author: bob 
Date:   Thu Mar 18 16:39:49 2010 +0000

love from vancouver



- 
http://www8.atwiki.jp/git_jp/pub/Documentation.ja/user-manual.html#merging-multiple-trees

github使


githubpushgithubgithubURLgit remotegithubssh

- http://github.com/repositories/new
- 
- 



$ cd ~/.ssh
既存の鍵ペアがある場合はバックアップをとります
$ mkdir key_backup
$ cp id_rsa* key_backup
$ rm id_rsa*
鍵ペアを生成します
$ ssh-keygen -t rsa -C "tekkub@gmail.com"

id_rsa_github

ssh~/.ssh/config
$ vi config
Host github.com
HostName github.com
User git
IdentityFile /home/suzukimilanpaak/.ssh/id_rsa_github

Permission denied (publickey).
ssh -v git@github.com

xclip使
$ sudo apt-get install xclip
$ cat ~/.ssh/id_rsa.pub | xclip -sel clip
xclipでクリップボードに公開鍵の内容が保存されているので、それを以下のページのKeyという項目に張り付けます
https://github.com/account#ssh_bucket
titleの項目は任意です。

~/workspace/git$ git clone alice snippets
~/workspace/git$ cd snippets
リポジトリのアドレスは作成したリポジトリのページからコピーしてください
snippets$ git remote add -t master origin git@github.com:yourusername/code-snippets.git
snippets$ git pull


README
snippets$ vi README
This repo is for my private use only. thank you
何だかgithubの意に反したことを言っていますが。。。

snippets$ git add .
snippets$ git commit -am "added README"
snippets$ git push origin master


- Network Graph
http://github.com/yourusername/code-snippets/network


Eric Raymondgithub


Git + Apache + Basic


git使Apache使svn2009apachesmart HTTPGit > v1.6.6Apache 2.x 

UbuntuApacheDAVSmart HTTP


GitBasichttp.authanyHTTPSmart HTTP使


# DocumentRootの場所を探します
$ grep -r DocumentRoot /etc/apache2/*                                               */
# DocumentRootに移動
$ cd /var/www
$ sudo mkdir dev.git
# 裸のgitリポジトリを作成します。apacheユーザでアクセスするので--sharedオプションは使用しません。
$ sudo git --bare init
$ git update-server-info

# apacheユーザを検索(apacheが動作している前提)
$ ps aux |grep apache
www-data  1862  0.0  0.0  40064    52 ?        S    09:10   0:00 /usr/sbin/apache2 -k start
$ sudo chown -R www-data:www-data dev.git
$ cd /etc/apache2


Ubuntuapache2apptitudeapt-get/etc/apache2/mods-available/dav.load

DAVLockDBms_dav_fsSDBM使
$ grep -r DAVLockDB mods-available/*                                            */
mods-available/dav_fs.conf:DAVLockDB /var/lock/apache2/DAVLock
モジュールを有効にします。
$ sudo a2enmod dav dav_fs



$ sudo vi sites-available/git
NameVirtualHost *
<VirtualHost *>
ServerName <servername>
ServerAdmin a.hi.tech.hippie@@googlemail.com
DocumentRoot /var/www/dev.git
ErrorLog /var/log/apache2/error.dev.git.log

<Location />
DAV on
AuthType Basic
AuthName 'developer'
AuthUserFile /etc/apache2/.htbasic
Require valid-user
</Location>
</VirtualHost>

$ sudo vi /etc/hosts
127.0.0.1       <servername>
127.0.1.1       <servername>

$ htpasswd -c /etc/apache2/.htbasic <user>
$ /etc/init.d/apache2 restart

http://<servername>/ErrorLog

gitapache ~/.netrc~/netrc600
machine <servername>
login <user>
password <password>



Apacheclone
~/workspace/git$ git clone http://<servername>/ dev


curl使
curl --netrc --location -v http://<username>@<servername>/HEAD



~/workspace/git/dev$ touch work?
~/workspace/git/dev$ git add .
~/workspace/git/dev$ git commit -m "created work?" 
# masterブランチの内容をoriginにpush
~/workspace/git/dev$ git push origin master
Fetching remote heads...
refs/
refs/tags/
refs/heads/
updating 'refs/heads/master'
from 0000000000000000000000000000000000000000
to   bd4637936d5b8978b82ef06f8a8b6f75b716552f
sending 2 objects
done
Updating remote server info

Apachewritegit update-server-info

Git + Apache + BasicpushfetchGitHTTPPackfile(Git)Smart HTTPupload-packreceive-packApacheCGIpackfilepostGETSmart HTTP



- 




.