katapedia

Git

はじめての

絵があって簡単で面白い

↓↓↓↓↓↓↓↓↓↓↓↓

http://kinokoru.jp/archives/1017

アニメーションで面白い

↓↓↓↓↓↓↓↓↓↓↓↓

http://k.swd.cc/learnGitBranching-ja/

コミット取り消し

http://freak-da.hatenablog.com/entry/20111105/p1

コマンド

_.コマンド _.意味
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 管理対象外のファイルを削除する

初期設定

git config --global user.name "your name"
git config --global user.email aaa@gmail.com
git config --global color.ui auto

ヘッドの種類

http://tkengo.github.io/blog/2014/02/10/how-to-track-git-history/

違い

resetオプションの違い

コミットメッセージだけ修正してコミットし直したい:git reset –soft

変更内容を追加してコミットし直したい:git reset –mixed

コミット自体なかったことにしたい:git reset –hard

世代のたどり方

Gitの中身

中の挙動が詳しく書いてある

http://koseki.hatenablog.com/entry/2014/04/22/inside-git-1

コミットメッセージ規約

  1. WhyやHowを書くこと。 WhereやWhatはいらん、diffを見ればわかる
  2. 言語は英語にする(最初の1文は必ず英語。そのあと補足で日本語は可)
  3. 1文の場合にはピリオドを付けない
  4. 主語は省き時制は現在の文章形式にする
  5. 文頭の英単語を大文字にする
  6. ファーストコミットは「Initial commit」 とする
  7. issueから発生したコミットは先頭に「[refs #”issue番号”]」を記述する。クローズの場合は[close #”issue番号”]
  8. 命令形とする http://stackoverflow.com/questions/3580013/should-i-use-past-or-present-tense-in-git-commit-messages/8059167#8059167

コミットメッセージでよく使う英語

Gitリポジトリブラウザ比較

Gitリモートリポジトリでgit init –bare –sharedを付け忘れた場合

git config core.sharedRepository group
chmod -R g+ws hooks
chmod -R g+ws info
chmod -R g+ws objects
chmod -R g+ws refs

で–shareと同じ効果

ブランチの定義

issue-XXX/(大分類名)/ブランチ名で命名

issue-123/chat_timeline/extract-url_linkみたいな感じ

  1. developブランチ 開発を行うためのブランチ。開発者は、主にこのブランチ上で作業を行う。次に紹介するfeatureブランチなど、他のブランチで行った作業は、ここにマージされる

  2. featureブランチ 主要な機能を実装するためのブランチ。機能の実装やバグフィックスなど、タスクごとにfeatureブランチを作成し、作業を行う

  3. releaseブランチ リリースの準備を行うためのブランチ。プロダクトをリリースする前に、このブランチを作成し、微調整を行う。releaseブランチを作成することで、リリース準備と次のバージョンに向けた開発のコードを分けることができる

  4. masterブランチ リリースしたソースコードを管理するためのブランチ。リリース作業を行うと、releaseブランチはmasterブランチへマージされて、リリースタグが打たれる。開発者は、このブランチへのコミットは行わない

  5. hotfixブランチ リリースされたソフトウェアに緊急の修正を行うためのブランチ。このブランチでの修正内容は、すぐにリリースされるので、hotfixブランチはリリースを管理するmasterブランチへマージされる

ルール

原則

Gitワークフロー

リポジトリ名規約

便利なコマンドとオプション

リポジトリ名取得

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 diff <branch name> --shortstat *.cc

git log --author="Taro Tanaka" --oneline --shortstat

git log --numstat --pretty="%H" | awk 'NF==3 {plus+=$1; minus+=$2} END {printf("+%d, -%dn", plus, minus)}'

総追加行数

git log --since=2013-01-01 --until=2013-06-30 --oneline --numstat --no-merges --pretty=format:"" | cut -f1 | awk 'BEGIN {sum=0} {sum+=$1} END {print sum}'
git log -- <branch name> --oneline --numstat --no-merges --pretty = format: "" | cut -f1 | awk 'BEGIN {sum=0} {sum+=$1} END {print sum}'
git log --since=2015-09-01  --oneline --no-merges --numstat --pretty=""  *.cc *.h  | cut -f1  | awk 'BEGIN {sum=0} {sum+=$1} END {print sum}'

総削除行数

git log --since = 2013-01-01 --until = 2013-06-30 --oneline --numstat --no-merges --pretty = format: "" | cut -f2 | awk 'BEGIN {sum=0} {sum+=$1} END {print sum}'

コントリビューター一覧

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の削除

git submodule deinit vendor/pelican-sober
git rm vendor/pelican-sober
rm -rf .git/modules/path/to/submodule
git commit -a

履歴を保持したままリポジトリを統合する

# Fetch the submodule commits into the main repository
git remote add submodule_origin git://url/to/submodule/origin
git fetch submodule_origin

# Start a fake merge (won't change any files, won't commit anything)
git merge --allow-unrelated-histories -s ours --no-commit submodule_origin/master

# ここでgit log しても表示されない

# Do the same as in the first solution
git rm --cached submodule_path # delete reference to submodule HEAD
git rm .gitmodules             # if you have more than one submodules,
# 他のsubmoduleがある場合はviで対象部分のみ削除
# you need to edit this file instead of deleting!
rm -rf submodule_path/.git     # make sure you have backup!!
git add submodule_path         # will add files instead of commit reference


# Commit and cleanup
git commit -m "removed submodule"
# ここでgit log したら表示される
git remote rm submodule_origin

https://stackoverflow.com/questions/1759587/un-submodule-a-git-submodule

Tips

git diffで特定のハッシュと一つ前を比較する

git diff 15dc8^!

https://stackoverflow.com/questions/436362/how-to-diff-a-commit-with-its-parent/449128#449128

過去のコミットの名前を全書き換えする

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を一括で修正する

for i in $(git ls-files | xargs -i file {} | grep --line-buffered "ASCII\|UTF-8" | cut -d ":" -f 1); do  echo $i; \
 if diff /dev/null "$i" | tail -1 | \
  grep '^\\ No newline' > /dev/null; then echo >> "$i"; \
fi; done

一括で改行コードを修正する

git ls-files | xargs -i file {} | grep --line-buffered "ASCII\|UTF-8" | cut -d ":" -f 1 | xargs -i nkf  -Lu --overwrite {}

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 rest –hard xxx

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”

でかいファイルをコミットしてしまった場合

重いファイルをコミットした場合、ツリーから消さない限りリポジトリが重くなってしまう。

git filter-branch --force --index-filter  'git rm --cached --ignore-unmatch でかいファイル.tar.gz'  --prune-empty --tag-name-filter cat -- --all

これでツリー上から完全削除される

http://www.walbrix.com/jp/blog/2013-10-github-large-files.html

“軽量化の仕方”:http://techracho.bpsinc.jp/baba/2012_05_22/5594

でかくなったリポジトリの原因を特定する

これが一番良さそう

#my problem was that I had there a refs/remotes/origin/master line for a remote repository, delete it, otherwise git won't remove those files
check .git/packed-refs
#(optional)to check for the largest files
git verify-pack -v .git/objects/pack/#{pack-name}.idx | sort -k 3 -n | tail -5
#(optional)to check what are those files
git rev-list --objects --all | grep a0d770a97ff0fac0be1d777b32cc67fe69eb9a98
#to remove a file from all revisions
git filter-branch --index-filter 'git rm --cached --ignore-unmatch file_names' -- --all
#to remove git's backup
rm -rf .git/refs/original/
rm -rf .git/logs/
git reflog expire --expire=now --all
git gc --prune=now
git gc --aggressive --prune=now

# old
#to expire all the loose objects
#git reflog expire --all --expire='0 days'
#to check if there are any loose objects
#git fsck --full --unreachable
#repacking
#git repack -A -d
#to finally remove those objects
#git prune

リモートリポジトリにあげたら容量がもとに戻ってしまうので、リモートリポジトリを一旦削除して再度pushする必要がある。

http://stackoverflow.com/questions/2164581/remove-file-from-git-repository-history

gitのリポジトリがでかくなったときの削減の昔のやり方

一部のファイルだけ違うブランチのものを使う

git checkout ブランチ名 ファイル名

コミットするユーザやメールアドレスを間違えた場合

コミット時のユーザやメールアドレスを変更するとき

git commit –amend –author=”sea_mountain dummy_email_address@example.com

結構前のコミットするユーザやメールアドレスを間違えた場合

$ git rebase -i <コミット>

  1. エディタが開くので以下のように変更して保存
  2. (変更後)対象のコミットをeditに変更 $ git commit –amend -m “コミットメッセージ” –author=”user.name "

$ 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

公式文書は難解なので。。。

リモートリポジトリのコミットログを修正する

  1. git checkout -b ローカルのブランチ名 origin/リモートのブランチ名 でブランチを切ります。
  2. git rebase -iします。
  3. git push origin +ローカルのブランチ名:リモートのブランチ名 して強制的にコミットツリーを変更します。 他のリポジトリから変更を取得する際は、git fetchしてgit rebase origin/リモートのブランチ名 としましょう。

コミット日付をタイムスタンプに復元

for FILE in `git ls-files`; do
TIME=`git log --pretty=format:%ci -n1 $FILE`
echo $TIME't'$FILE
STAMP=`date -d "$TIME" +"%y%m%d%H%M.%S"`
touch -t $STAMP $FILE
done

Gitのルートディレクトリに移動する

cd “$(git rev-parse –show-toplevel)”

commitの際にオーナー情報を入れていなかった

git config --global user.name "your name"
git config --global user.email aaa@gmail.com
git commit --amend --reset-author

OR

.gitconfig

[user]
name = name
email = mail@gmail.com

Gitでプロキシを通すURLと通さないURLを使い分ける

どうやらversion:1.8ではダメのよう

~/.gitconfig

[http "http://192.168.1.30"]
postBuffer = 524288000
proxy =
[http "http://192.168.1.40"]
postBuffer = 524288000
proxy =
[http "http://192.168.1.50"]
postBuffer = 524288000
proxy =
#[http]
#    postBuffer = 524288000
#    proxy = http://192.168.1.30:10080
#[https]
#    postBuffer = 524288000
#    proxy = http://192.168.1.30:10080
[url "https://"]
insteadOf = git://

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

[url "http://github.com/"]
insteadOf = git@github.com:

Gitで大量のファイルの中から必要ファイルのみをaddする方法

CentOS6.x系でhttp認証に失敗する

GitのGUI比較

現在のディレクトリで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