Memo/git

http://dexlab.net/pukiwiki/index.php?Memo%2Fgit
 


git


reflog: やりすぎたresetや削除したbranchを戻す

reset --hardをやりすぎた時に戻す。
削除したbranchを戻す。
ただし、コミットしてないファイルは戻ってこない。

  • resetを戻す
    1. # 直近4つまでの作業ログを見る
    2. git reflog -n 4
    3.  
    4. # 戻したい所まで戻す
    5. git reset --hard <HEAD@{N} or commit id>
  • 削除したbranchを戻す
    1. # 直近4つまでの作業ログを見る
    2. git reflog -n 4
    3.  
    4. # <HEAD@{N}>を元に <branch name> を作る
    5. git branch <branch name> <HEAD@{N} or commit id>

書籍

  • Git - Book 無償。web, pdf, epub, mobi形式で読める

.gitignore 特定パターンを無視

.gitignore に入れたパターンは「git status」等で差分として表示されなくなる
親フォルダにまとめて記載しておけば、子フォルダにも適用される。

  1. # vimの作業ファイル
  2. *.swp
  3.  
  4. # subversionのディレクトリ
  5. .svn/
  6.  
  7. # macOSの不要ファイル
  8. .DS_Store
  9.  
  10. # windowsの不要ファイル
  11. Thumbs.db
  12.  
  13. # ansibleのリトライファイル
  14. *.retry

間違ったmergeを取り消す

  • Git-flowって何? - Qiita
    • 通常:developブランチからreleaseブランチを作る。「git co -b release/1.10」
    • 誤り:developブランチをreleaseブランチへマージする。「git merge release/1.10」
    • 誤り:developブランチをdevelopブランチへマージする。「git merge develop」
  • git log --graphで見た時、以下のようなツリーになってしまう
    1. *   a1234567 - user01 -  Merge branch 'develop' into release/1.10 (x hours ago)
    2. |\  
    3. | *   b1234567 - user02 -  Merge branch 'release/1.10' into develop (x days ago)
    4. | |\  
    5. | * \   c1234567 - user03 -  Merge branch 'release/1.10' into develop (x days ago)
    6. | |\ \  
    7. | * \ \   d1234567 - user04 -  Merge tag 'v1.10.0' into develop (x days ago)
    8. | |\ \ \  
    9. | * \ \ \   e1234567 - user04 -  Merge branch 'release/1.10' into develop (x days ago)
    10. | |\ \ \ \  
    11. | * \ \ \ \   f1234567 - user03 -  Merge branch 'release/1.10' into develop (x days ago)
    12. ...
  • 修正: release/1.10へのマージ「a1234567」 が間違っているので、「a1234567」 を取り消す
    1. # git log --graph で誤り前のコミットidを探す。この例では「aa123456」とする
    2. git reset aa123456 --hard
    3.  
    4. # treeを見て間違ったマージより先に取り込みたいコミットがあれば、cherry-pickやmergeで取り込む
    5. git cherry-pick <commid it>
    6. git merge <commid it>
    7.  
    8. # force pushで強制的に修正
    9. git push -f origin release/1.10
  • localリポジトリも更新する必要がある
    1. git fetch
    2. git co origin/release/1.10
    3. git pull -p

git logから削除されたファイルを探す

  1. git log --diff-filter=D --summary <path>

--force-with-lease

「--force」より安全らしい

  • git push --force
    • ローカルリポジトリでリモートリポジトリを上書きする
  • git push --force-with-lease
    • 他人がpushしていたら、失敗する。
    • 自分の修正後に、他人がpushしていたら「--force」を使うしかない

authorを後から変更

  1. git commit --amend --author="user <user@example.com>"

パーミッション変更を無視する

Linuxで開発しているリポジトリをWindowsでcloneして編集しようとすると、パーミッションの違いが検出されて邪魔な時がある。

  1. git config core.filemode false
  2.  
  3. # 確認
  4. git config -l | grep core.filemode

空白を無視して比較

  • diff
    1. diff -uw file-a file b
  • git (-b でインデントを無視)
    1. git diff -w
  • GitHub?: URLの末尾に「?w=1」を付ける
  • BitBucket?: URLの末尾に「?w=1」を付ける
    • または「・・・」をクリックして「ignore whitespace」にチェック

git-secrets: AWSキー等をgithubに流出するのを防ぐ

うっかりAWSキー等がgithubに流出している事故が多い。
(実際に流出するとAWSからメールが来て、AWSアカウントが制限状態になる。該当キーを削除するまで続く)

  • https://github.com/awslabs/git-secrets
    • AWSキー等を誤ってコミットする事を防いでくれるフックが追加される
    • スペースを含むファイルのcommitに失敗する場合、「git pull;make install」で直った
  • CentOS6.xの場合
    1. # インストール
    2. git clone https://github.com/awslabs/git-secrets.git
    3. cd git-secrets/
    4. sudo make install
    5.  
    6. # 全体設定に追加
    7. git secrets --register-aws --global
    8. git secrets --install ~/.git-templates/git-secrets
    9. git config --global init.templatedir '~/.git-templates/git-secrets'
    10.  
    11. # 既存プロジェクトに追加
    12. git secrets --install /path/to/repository
    13.  
    14. # 既存ディレクトリをチェック
    15. git secrets --scan -r /path/to/repository
  • フックを削除したい場合
    1. # 確認
    2. find /path/to/repository/.git/hooks/ -type f ! -name "*.sample"
    3.  
    4. # 削除
    5. find /path/to/repository/.git/hooks/ -type f ! -name "*.sample" -delete

merge: マージ

  • マージする履歴を残す (--no-ff)
    1. git merge --no-ff topic

リモートブランチとローカルブランチを強制的に一致させる

  • 例:masterブランチを一致させる。ローカルの変更点はすべて破棄されるので注意
    1. git fetch origin
    2. git reset --hard origin/master

git-flow

CentOS6.xにgit v2.xをインストール

  • iusリポジトリにある
    1. # 古いgitは削除
    2. sudo yum erase git
    3. # EPELリポジトリも必要
    4. sudo yum install http://dl.iuscommunity.org/pub/ius/stable/CentOS/6/x86_64/epel-release-6-5.noarch.rpm
    5. sudo yum install http://dl.iuscommunity.org/pub/ius/stable/CentOS/6/x86_64/ius-release-1.0-14.ius.centos6.noarch.rpm
    6. sudo yum install git2u
    7.  
    8. # バージョン確認
    9. git --version
    10. git version 2.4.3
    11.  
    12. # bashプロンプトにブランチ名を表示する場合
    13. sudo cp /usr/share/git-core/contrib/completion/git-prompt.sh /etc/bash_completion.d/

CentOS6.xにgit v1.7.2をインストール

  • CentOS6.x baseリポジトリだとgit v1.7.1がインストールされる
  1. rpmforge リポジトリを使えるようにする
  2. インストール
    1. sudo yum install --enablerepo=rpmforge-extras git
    2.  
    3. git --version
    4. git version 1.7.12.4
    • /etc/bash_completion.d/git が更新されて、プロンプトにブランチ名の表示が動かなくなったので更新
      1. sudo wget --no-check-certificate -O /etc/bash_completion.d/git-prompt.sh https://raw.githubusercontent.com/git/git/master/contrib/completion/git-prompt.sh
      2. source /etc/bash_completion.d/git-prompt.sh

gitの設定を表示

  • gitコマンドで取得
    1. git config -l --global
  • catでも同じ
    1. cat ~/.gitconfig

git bisect: 二分探索によって問題箇所を特定する


subtree: 外部リポジトリを取り込む


Mac OS Xにgitクライアントのインストール

  • brewの場合
    1. brew install git
    2. echo 'export PATH=/usr/local/Cellar/git/2.7.0/bin:$PATH' >> ~/.bash_profile
    3. source ~/.bash_profile
  • MacPorts?を使う場合。後でブランチ名の表示等で +bash_completion が必須となるのでこちらの方がよさそう
    1. sudo port install git +svn +doc +bash_completion +gitweb
  1. git−1.7.2.2-intel.leopard.pkg を実行
  2. ターミナルからパスを通すスクリプトを実行
    1. ./setup\ git\ PATH\ for\ non-terminal\ programs.sh
  3. ターミナルの再起動。gitコマンドで使えるか確認

空ディレクトリをgitに入れる

そのままだと管理されないので".gitkeep"ファイルを入れる

  1. mkdir dummy
  2. touch dummy/.gitkeep
  3. git add dummy

ワークフロー


リモートで削除されたブランチをローカルから削除

  1. git fetch --prune origin

tag: 別名を付ける

  • コミットに別名を付ける release/1.00 等
  • tagを指定してチェックアウトが可能
  • tag自体はバージョン管理されない
  • 使い方
    1. # タグをリモートと同期
    2. git fetch --tags
    3.  
    4. # タグの作成
    5. git tag release/1.00
    6. git tag release/1.01
    7.  
    8. # タグ一覧 (-n でアノテーションタグも表示)
    9. git tag -n
    10. release/1.00
    11. release/1.01
    12.  
    13. # ローカルタグ削除
    14. git tag -d release/1.01
    15.  
    16. # リモートにpush。このままpushしてもリモートのタグは消えない
    17. git push origin release/1.01
    18. # または、以下(意図しないタグまでpushされる可能性がある)
    19. git push --tags
    20.  
    21. # リモートのタグ削除
    22. git push --delete origin release/1.01
  • 注釈(アノテーション annotation)付タグ。タグ名以外に任意の注釈を付けられる
    1. git tag -a release/1.02 hogehoge
    2.  
    3. git tag -n
    4. release/1.02    hogehoge
  • タグのリネーム。タグは同じcommit hashに複数付けられる
    1. git tag
    2. release/1.00
    3. release/1.01
    4. release/1.02
    5.  
    6. # リネームしたいcommit hashを確認
    7. git rev-parse release/1.01
    8. e2f61a85745f777a720227594fa3442dfbd15647
    9.  
    10. # git tag new-tag old-tag
    11. git tag release/1.01.new release/1.01
    12.  
    13. # 新しいタグのcommit hashが同じか確認
    14. git rev-parse release/1.01.new
    15. e2f61a85745f777a720227594fa3442dfbd15647
    16.  
    17. # delete local old tag
    18. git tag -d release/1.01
    19.  
    20. git tag
    21. release/1.00
    22. release/1.01.new
    23. release/1.02
    24.  
    25. git push origin --tags
    26.  
    27. # delete remote old tag
    28. git push --delete origin release/1.01

cherry-pick: 特定のコミットだけを適用する

  • 例:別branchのコミット:99daed2 だけをmasterに適用する
    1. git checkout master
    2. git cherry-pick 99daed2

cherry-pick中止

  • エラーが発生
    1. error: a cherry-pick or revert is already in progress
  • 中止
    1. git cherry-pick --abort

範囲を指定してcherry-pick

  • git v1.7.2以上
    1. git cherry-pick master..next

リモートリポジトリのURLを変更したい場合

  1. git remote -v
  2. git remote set-url origin <新しいリポジトリのURL>

bash用コマンド補完とプロンプトにブランチを表示

  • git [tabキー] または git log [tabキー]等でコマンドが補完できるようになる
  • 現在のブランチをプロンプトに表示 [host@user:path (branch)]
  • CentOS 6/7
    1. sudo yum install bash-completion --enablerepo=epel
    2. sudo cp /usr/share/git-core/contrib/completion/git-prompt.sh /etc/bash_completion.d/
    3.  
    4. cat >> ~/.bashrc << 'EOS'
    5. if [ -f /etc/bash_completion ]; then
    6.     . /etc/bash_completion
    7. else
    8.     [ -n "$BASH_COMPLETION" ] || BASH_COMPLETION=/etc/bash_completion
    9.     [ -n "$BASH_COMPLETION_DIR" ] || BASH_COMPLETION_DIR=/etc/bash_completion.d
    10.     [ -n "$BASH_COMPLETION_COMPAT_DIR" ] || BASH_COMPLETION_COMPAT_DIR=/etc/bash_completion.d
    11.     readonly BASH_COMPLETION BASH_COMPLETION_DIR BASH_COMPLETION_COMPAT_DIR
    12. fi
    13.  
    14. if [ -f $BASH_COMPLETION_DIR/git-prompt.sh ]; then
    15.     export PS1=${PS1/W\]/W\$(__git_ps1)]}
    16. #    export PS1="[\h@\u:\W\$(__git_ps1)]\$ "
    17. fi
    18. EOS
    19.  
    20. source ~/.bashrc
  • Mac OS X Mavericks + git 2.0.1 (+bash_completion 付)
    • /opt/local/etc/bash_completion.d/git-prompt.sh が無かったり、$BASH_COMPLETION_DIR が空だったので試行錯誤した
      1. sudo port install bash-completion
      2. sudo cp /opt/local/share/git/git-prompt.sh /opt/local/etc/bash_completion.d/
      3.  
      4. cat >> ~/.profile << 'EOS'
      5. if [ -f /opt/local/etc/bash_completion  ]; then
      6.     . /opt/local/etc/bash_completion
      7. fi
      8. if [ -f /opt/local/etc/bash_completion.d/git-prompt.sh ]; then
      9.     . /opt/local/etc/bash_completion.d/git-prompt.sh
      10.     export PS1='\h:\W \u$(__git_ps1)\$ '
      11. fi
      12. EOS
      13.  
      14. source ~/.profile

GUIクライアント

  • Github for Windows
    • msysGit ベース
    • Git Shellもインストールされる
    • シェルを複数から選べる。tools > option > default shell: Cmd, Git Bash, PowerShell?, Custom
    • 英語UIのみ

改行コードの自動変換を止める

git for windowsではデフォルトで、改行コードの自動変換される。

  • チェックアウト時:LFをCRLFへ変換
  • コミット時:CRLFをLFへ変換
  1. vi ~/.gitconfig
  2. ----
  3. [core]
  4.     autoCRLF = false
  5. ----

reset:取り消し

  • 現在のコミットを取り消し、一つ前のコミットまで戻す
    1. # ワーキングディレクトリはそのままで、コミットだけ取り消す
    2. git reset --soft HEAD^
    3.  
    4. # コミットを取り消し、ワーキングディレクトリも戻す
    5. git reset --hard HEAD^

diff:差分

  • 空白の違いを無視(-w)
    1. git diff -w
  • カラー表示
    1. git config --global color.ui auto
  • 直前の差分を表示
    1. git diff HEAD^ .
  • 単語単位で差分表示
    1. git diff --word-diff
  • 異なるブランチの同じファイルを比較
    1. git diff master branch1 path/foo.txt
  • 異なるブランチの異なるファイルを比較
    1. git diff master:path/foo.txt branch1:path/bar.txt

branch:ブランチ

  • ブランチ名の変更
    1. git branch -m <old branch> <new branch>
    2. # または、現在のブランチ名を変更
    3. git branch -m <new branch>
  • ローカルとリモートのブランチ一覧
    1. git branch -a
  • 作業用のローカルブランチを作成
    1. git checkout -b hoge-prototype
    2.  
    3. git branch
    4. * hoge-prototype
    5.   master
    6.  
    7. # リモートに同名ブランチとしてpush
    8. git push origin hoge-prototype
  • 現在のローカルブランチをリモートへpush
    1. git push -u origin HEAD
  • ブランチを削除
    1. # カレントをmasterに変更
    2. git checkout master
    3.  
    4. # ローカルブランチを削除
    5. git branch -d hoge-prototype
    6.  
    7. # 同名のリモートブランチを削除
    8. git push --delete origin hoge-prototype
    9.  
    10. # または':'
    11. git push origin :hoge-prototype

patchコマンド用diffファイルの作成

  1. git diff --no-prefix HEAD~ > hoge.patch
  2. patch --dry-run -p0 < hoge.patch
  3. patch -p0 < hoge.patch

stash:変更を一時的に待避

  • 誰かが変更中のファイルがあるが、最新に更新したい
    1. git pull
    2. error: Your local changes to the following files would be overwritten by merge:
    3.         example/hoge.txt
    4.  
    5. # 変更を待避(git stash saveと同じ)
    6. git stash
    7.  
    8. # 最新に更新
    9. git pull
    10.  
    11. # 保存したワークツリーを戻す
    12. git stash pop
    13.  
    14. git push

brame:誰が行を変更したのかを探す

  • file.txtの5行目を誰が変更したかを見る
    1. git blame -L 5 file.txt
    2. d23bebd3 (username 2013-01-02 10:54:57 +0900  5) 05 change
    3.  
    4. # 5-6行目を誰が変更したかを見る。オフセット指定もできる。-L 5,+1
    5. git blame -L 5,6 file.txt
    6. d23bebd3 (username 2013-01-02 10:54:57 +0900 5) 05 change
    7. 469dbe58 (username 2013-01-02 11:04:25 +0900 6) 06 change

.gitconfig

  • /.gitconfig

    1. [core]
    2.         editor = vim
    3. [color]
    4. ui = auto
    5. [alias]
    6. ad = add
    7. br = branch
    8. ci = commit
    9. cia = commit --amend
    10. cih = commit --amend -C HEAD
    11. cih1 = commit --amend -c HEAD@{1}
    12. co = checkout
    13. d = diff
    14. dc = diff --cached
    15. dn = diff --name-only
    16. dw = diff --color-words
    17. ft = fetch
    18. l = log --oneline -n 20
    19. lg = log --graph --pretty=format:'%Cred%h%Creset - %an - %C(yellow)%d%Creset %s %Cgreen(%cr)%Creset' --abbrev-commit --date=relative
    20. lgraph = log --oneline --graph --decorate --all -n 20
    21. lp = log --oneline -n 20 -p
    22. ls = log --stat -n 1
    23. pl = pull
    24. ps = push
    25. rb = rebase
    26. rbh = rebase HEAD
    27. rbo = rebase --onto
    28. rl = reflog show -n 20
    29. rs = reset
    30. rsh = reset --hard
    31. sb = show-branch
    32. sh = show
    33. share = daemon --verbose --base-path=/home/sinsoku/repos/ --enable=receive-pack
    34. so = remote show origin
    35. st = status -s

fatal: The remote end hung up unexpectedly

公開鍵(~/.ssh/id_rsa.pub)/秘密鍵(~/.ssh/id_rsa)が無いと起きる

  • 作成
    1. ssh-keygen -t rsa

svn exportと同様に使う

  • /tmp/foo を作らないと /tmp/直下にファイルが散乱する
    1. mkdir /tmp/foo
    2. git archive master | tar -x -C /tmp/foo

origin等の別名をつける

よくoriginやmasterといった名前が出てくるが、これは".git/config" に記載があるため。
直接編集しても結果は同じ

  • .git/configに記載がある
    1. cat .git/config
    2.  
    3. [core]
    4.         repositoryformatversion = 0
    5.         filemode = true
    6.         bare = false
    7.         logallrefupdates = true
    8. [remote "origin"]
    9.         fetch = +refs/heads/*:refs/remotes/origin/*
    10.         url = git://github.com/heroku/ruby-sample.git
  • "origin"という別名を付ける
    1. git remote add origin git://github.com/heroku/ruby-sample.git

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-04-16 (月) 15:38:50 (9d)