Git
はじめての
絵があって簡単で面白い
↓↓↓↓↓↓↓↓↓↓↓↓
http://kinokoru.jp/archives/1017
アニメーションで面白い
↓↓↓↓↓↓↓↓↓↓↓↓
http://k.swd.cc/learnGitBranching-ja/
コミット取り消し
http://freak-da.hatenablog.com/entry/20111105/p1
コマンド
commitする バージョンを1つ進める
stageする 特定の変更内容をindexに登録する(次回commit分に含める)
index 次回commit分のファイル一覧
|.コマンド|.意味|
|git init|カレントディレクトリ以下をgit管理下に置く|
|git add |をstageする。に.(ピリオド)を指定すると変更分全て|
|git commit -m "" | 1行メッセージ付きでcommitする|
|git status | stage(to be commited)と変更分(not updated)の状態を確認する|
|git reset []| (git logで表示されるハッシュ文字列部分)まで戻る。指定が無ければindexを全てunstageする|
|git log [--format=oneline]|commitの履歴を見る。オプションでformatが幾つか指定出来る|
|git rm|ファイルを削除してgitに削除したことを伝える|
|git clean -fdxn ←確認 危険!必ず確認すること 実行→ git clean -fdx |管理対象外のファイルを削除する|
初期設定
ヘッドの種類
HEAD 現在作業しているワーキングツリーのコミットを指します。コミットが重なる度に先頭へ移動していきます。また git reset や git merge git rebase などのコマンドでも移動します。
ORIG_HEAD git reset や git merge など、通常のコミットとは違う極端な HEAD の移動が発生した時に、移動前の HEAD のコミットを指します。
MERGE_HEAD git merge を実行して、コンフリクトなどが発生してマージをしている最中にマージ元のブランチの先頭のコミットを指します。
CHERRY_PIKC_HEAD MERGE_HEAD とほぼ同じですが git cherry-pick を実行した場合のものです。
FETCH_HEAD git fetch した時、リモートから取得したコミットの先頭のコミットを指します。
http://tkengo.github.io/blog/2014/02/10/how-to-track-git-history/
違い
resetオプションの違い
コミットメッセージだけ修正してコミットし直したい:git reset --soft
変更内容を追加してコミットし直したい:git reset --mixed
コミット自体なかったことにしたい:git reset --hard
世代のたどり方
^ について ^ を指定することで、親のコミットを取得することができます。よく聞く話かとは思いますが git のコミットには必ず 1 つは親が存在します(一番最初のコミットを除いて)。親というのは要するに直前のコミットのこと。そしてマージが発生すると、そのマージコミットについては 2 つの親を持つことになります
~ について 親のコミットを取得できるのは ^ と同じなのですが ~ の方はマージコミットがあっても本流の方だけをたどっていきます。
Gitの中身
中の挙動が詳しく書いてある
http://koseki.hatenablog.com/entry/2014/04/22/inside-git-1
コミットメッセージ規約
WhyやHowを書くこと。 WhereやWhatはいらん、diffを見ればわかる
言語は英語にする(最初の1文は必ず英語。そのあと補足で日本語は可)
1文の場合にはピリオドを付けない
主語は省き時制は現在の文章形式にする
文頭の英単語を大文字にする
ファーストコミットは「Initial commit」 とする
issueから発生したコミットは先頭に「[refs #"issue番号"]」を記述する。クローズの場合は[close #"issue番号"]
命令形とする http://stackoverflow.com/questions/3580013/should-i-use-past-or-present-tense-in-git-commit-messages/8059167#8059167
Gitリポジトリブラウザ比較
Gitlab
Gitosis
Gitolite
Gitorious インストールが難しいらしい
Gitblit インストール簡単だが、機能がまだそろっていないらしい
Gitリモートリポジトリでgit init --bare --sharedを付け忘れた場合
で--shareと同じ効果
ブランチの定義
issue-XXX/(大分類名)/ブランチ名で命名
issue-123/chat_timeline/extract-url_linkみたいな感じ
developブランチ 開発を行うためのブランチ。開発者は、主にこのブランチ上で作業を行う。次に紹介するfeatureブランチなど、他のブランチで行った作業は、ここにマージされる
featureブランチ 主要な機能を実装するためのブランチ。機能の実装やバグフィックスなど、タスクごとにfeatureブランチを作成し、作業を行う
releaseブランチ リリースの準備を行うためのブランチ。プロダクトをリリースする前に、このブランチを作成し、微調整を行う。releaseブランチを作成することで、リリース準備と次のバージョンに向けた開発のコードを分けることができる
masterブランチ リリースしたソースコードを管理するためのブランチ。リリース作業を行うと、releaseブランチはmasterブランチへマージされて、リリースタグが打たれる。開発者は、このブランチへのコミットは行わない
hotfixブランチ リリースされたソフトウェアに緊急の修正を行うためのブランチ。このブランチでの修正内容は、すぐにリリースされるので、hotfixブランチはリリースを管理するmasterブランチへマージされる
ルール
原則
masterで作業しない。ブランチを作って作業すること
ブランチでは1機能もしくは1バグのみ作業すること
メジャーバージョンは常に動くようにしておくこと
チケットとリンクをとれるようにすること
リポジトリ名規約
基本すべて小文字
"_"でなく"-"の方がよい(使っている人が多いかつかっこいい)
便利なコマンドとオプション
リポジトリ名取得
basename $(git remote show origin -n | grep "Fetch URL:" | sed 's/.*://;s/.git$//'
https://stackoverflow.com/questions/15715825/how-do-you-get-git-repos-name-in-some-git-repository
ブランチ表示ログ
git log --graph --branches --pretty=format:"%d [%h] "%s""
統計情報
変更行数
総追加行数
総削除行数
コントリビューター一覧
git shortlog -se | awk -F't' '{print $2,$3}'
総コミット回数
git log --since = 2013-01-01 --until = 2013-06-30 --oneline --no-merges | wc -l
よくマージしている人
git log --merges --format="%cn" | sort | uniq -c | sort -r | head
よく編集しているファイル
git log --name-only --pretty="format:" | grep -ve '^$' | sort | uniq -c | sort -r | head
よくfu*kって書く人
git log --pretty="format:%cn:%s" | grep fu.k | cut -d":" -f1 | sort | uniq -c | sort -r
submodule
一括更新
git submodule foreach --recursive 'git checkout master; git pull'
ルートリポジトリからsubmoduleを更新してpushしたい
git submodule foreach --recursive git add -A .
git submodule foreach --recursive git commit -m 'submodule commit message'
git push --recurse-submodules=on-demand
孫もいるなら
git submodule foreach --recursive git push origin master
じゃないとだめっぽい
https://ja.stackoverflow.com/questions/17501/git-submodule%E3%82%92%E8%A6%AA%E3%81%AE%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%A8%E5%90%8C%E6%99%82%E3%81%AB%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88-%E3%83%97%E3%83%83%E3%82%B7%E3%83%A5%E3%81%97%E3%81%9F%E3%81%84
2017 Q3にリリースされる予定のgitで孫がいてもpushできるようになる見込み
https://stackoverflow.com/questions/29564257/git-push-recurse-submodules-on-demand-is-not-truly-recursive
submoduleの削除
履歴を保持したままリポジトリを統合する
https://stackoverflow.com/questions/1759587/un-submodule-a-git-submodule
Tips
過去のコミットの名前を全書き換えする
git filter-branch -f --env-filter "GIT_AUTHOR_NAME='sea_mountain'; GIT_AUTHOR_EMAIL='valid_email@example.com'; GIT_COMMITTER_NAME='sea_mountain'; GIT_COMMITTER_EMAIL='valid_email@example.com';" HEAD
No newline at end of fileを一括で修正する
一括で改行コードを修正する
gitconfigにユーザー情報を入れたくない
GIT_AUTHOR_NAME="" GIT_AUTHOR_EMAIL=""
を定義しておけばよい
一部のファイルのみをstashする
stashしないファイルをgit addする git stash -k
git reset
# ステージからもとに戻す
ノンパスワード設定
ssh-keygen -t rsa -C "your.email@example.com" -b 4096
cat ~/.ssh/id_rsa.pub
確認
ssh -T git@example.com
あとは、
https:// を git@github.com:に切り替える
これを使えばhttpsをsshに置き換えてくれる
git config --global "url.git@github.com:.pushinsteadof" "https://github.com/"
push先とfetch先を変える
git remote set-url --push origin git@github.com:User/forked.git
pushurl = http://192.168.1.20/Test/hubot-rocketchat.git
http://sleepycoders.blogspot.jp/2012/05/different-git-push-pullfetch-urls.html
http://stackoverflow.com/questions/948354/default-behavior-of-git-push-without-a-branch-specified
複数のコミットをまとめる
git rebase -i xxx
pick->s
http://iwb.jp/git-commit-rebase-squash/
Troubleshooting
パスワードを入力するときに ( gnome-ssh-askpass:11826 ) : Gtk-WARNING **: cannot open display: とか言われる
unset SSH_ASKPASS
間違ってgit resetしてしまった
コミットしているなら git reflog
git rest --hard xxx
ステージングしている git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)")
git show xxx
git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)") xxx
http://stackoverflow.com/questions/7374069/undo-git-reset-hard-with-uncommitted-files-in-the-staging-area
ステージングしていない 諦める
EUCでコミットメッセージを書いてしまった
git filter-branch ~~f --msg-filter 'nkf -w' -~~ --all
http://hiroom2.jimdo.com/2015/07/09/git-filter-branch%E3%81%A7%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%82%92%E4%B8%80%E6%8B%AC%E5%A4%89%E6%8F%9B%E3%81%99%E3%82%8B/
gitignoreでホワイトリスト化できない
階層構造になっていると工夫しないと認識されない
という感じに階層分だけ最初に除外する。
ディレクトリがある場合は
/*
!/src/
/src/*
!/src/hello.c
というように上のディレクトリを一回対象外にして入れ直す
http://seesaawiki.jp/aki/d/.gitignore%20%A5%D5%A5%A1%A5%A4%A5%EB%A4%CE%BD%F1%A4%AD%CA%FD
.gitignoreが反映されない
git rm -r --cached .
git add .
git commit -m "Update .gitignore"
でかいファイルをコミットしてしまった場合
重いファイルをコミットした場合、ツリーから消さない限りリポジトリが重くなってしまう。
これでツリー上から完全削除される
http://www.walbrix.com/jp/blog/2013-10-github-large-files.html
"軽量化の仕方":http://techracho.bpsinc.jp/baba/2012_05_22/5594
でかくなったリポジトリの原因を特定する
これが一番良さそう
リモートリポジトリにあげたら容量がもとに戻ってしまうので、リモートリポジトリを一旦削除して再度pushする必要がある。
http://stackoverflow.com/questions/2164581/remove-file-from-git-repository-history
一部のファイルだけ違うブランチのものを使う
git checkout ブランチ名 ファイル名
コミットするユーザやメールアドレスを間違えた場合
コミット時のユーザやメールアドレスを変更するとき
git commit --amend --author="sea_mountain dummy_email_address@example.com"
結構前のコミットするユーザやメールアドレスを間違えた場合
$ git rebase -i <コミット>
エディタが開くので以下のように変更して保存
(変更後)対象のコミットをeditに変更 $ git commit --amend -m "コミットメッセージ" --author="user.name <user.email>"
$ git log
$ git rebase --continue
管理下のファイルの行末のスペース(trailing whitespace)を削除する
git ls-files | sed -i 's/[ t]*$//'
refspecやremoteやrefsやらがわからなくなったとき
以下のサイトにわかりやすく解説されている。
http://d.hatena.ne.jp/hokaccha/20120404/1333507076
公式文書は難解なので。。。
リモートリポジトリのコミットログを修正する
git checkout -b ローカルのブランチ名 origin/リモートのブランチ名 でブランチを切ります。
git rebase -iします。
git push origin +ローカルのブランチ名:リモートのブランチ名 して強制的にコミットツリーを変更します。 他のリポジトリから変更を取得する際は、git fetchしてgit rebase origin/リモートのブランチ名 としましょう。
コミット日付をタイムスタンプに復元
Gitのルートディレクトリに移動する
cd "$(git rev-parse --show-toplevel)"
commitの際にオーナー情報を入れていなかった
OR
.gitconfig
Gitでプロキシを通すURLと通さないURLを使い分ける
どうやらversion:1.8ではダメのよう
~/.gitconfig
Trivia
objectsディレクトリの中
idxファイル:インデックスを保持
pack ファイル:データ実体
おもしろいinitial commit
This is where it all begins...
Commit committed
Version control is awful
COMMIT ALL THE FILES!
The same thing we do every night, Pinky - try to take over the world!
Lock S-foils in attack position
This commit is a lie
I'll explain when you're older!
Here be Dragons
Reinventing the wheel. Again.
This is not the commit message you are looking for
Batman! (this commit has no parents)
FAQ
git@github.com形式でダウンロードできない場合
~/.gitconfig
現在のディレクトリでgit clone
git clone http://xxx .
※古いバージョンだとできない?v1.8系は無理だった。
.gitignoreに設定しているファイルがリモートに存在するエラーの解決法
エラー文:
error:The following untracked workding tree files would be overwritten by merge:
解決法:
ようわからんけど、gitでリモートのブランチにローカルを強制一致させたい時
git fetch
git reset --hard FETCH_HEAD
Last updated