tech_memo / git


tech_memo

トラブルシュート

コンフリクト発生時の対応

  • pushにしろ、pullにしろ、コンフリクトが発生した場合にやることは同じ
  1. ローカルの編集中のファイルはgit commitか、git checkoutして未編集状態にする
  2. git pullして、リモートの変更を取り込む
  3. このとき、自動マージできないコンフリクトが発生した場合、vi等、手動編集で変更を取り込む。以下はコンフリクトが発生したファイルの例。
    <<<<<<<< HEAD
    ローカルの編集内容
    =======
    リモートの取り込むべき内容
    >>>>>>>> 72616890b37a0fb7b2f8cadf83524ed591430d5f
  4. git commitして、マージをローカルに適用
  5. git pushでリモートに適用。解決。

HTTPでのgit pushができない

  • apacheユーザでリポジトリへの書き込み権限が必要。
    chown -R <リポジトリパス>
  • または
    chmod -R o+w <リポジトリパス>

git cloneで、(gnome-ssh-askpass:28635): Gtk-WARNING **: cannot open display:

  • 以下の環境変数が設定されていると、CUI環境で発生する
    shishimaru@v-cent65% printenv SSH_ASKPASS  
    /usr/libexec/openssh/gnome-ssh-askpass
  • 上記はGUI環境を必要とするプログラムの模様。GUI環境だと gnome-ssh-askpass プログラムがパスワードをキャッシュしてくれるらしい。
  • CUIの場合の回避方法はいくつかある
  1. SSH_ASKPASS環境変数をアンセットする
    shishimaru@v-cent65% unset SSH_ASKPASS
  2. 自前でパスワードをechoするシェルを用意して、そのスクリプトを環境変数に設定する
    shishimaru@v-cent65% export SSH_ASKPASS=/home/shishimaru/git_pass.sh
    • git_pass.sh
      #!/bin/bash
      echo <PASSWORD>
  3. cloneするときのURLにユーザ名とパスワードを含める
    shishimaru@v-cent65% git clone http://shishimaru:<PASSWORD>@v-cent65:8180/shishimaru/myproject.git

リモートリポジトリの内容をローカルに強制反映する

  • 参考 : http://qiita.com/ms2sato/items/72b48c1b1923beb1e186
  • リモートでは管理済だが、ローカルで未管理の同名ファイルがある場合、git pullするとエラーになる。
  • リモートを正にしてローカルに強制取込みする際に以下のコマンドが利用できる。
    git fetch origin
    git reset --hard origin/master
  • なお、リモート未管理で、ローカルにあるファイルは以下のようになる。
    • ローカルでコミット済 ⇒ 消える
    • ローカルで未コミット ⇒ そのまま残る

空ディレクトリをgit addする方法

  • 参考 : http://phiary.me/git-empty-directory-add/
  • tmpディレクトリを空として登録する例(実際は1ファイルだけ登録して、それ以外は.gitignoreで無視させるという手法)
  • tmpディレクトリの下に.gitkeepというファイルを作成(名前はなんでもOK)
    tmp/.gitkeep
  • .gitignoreに.gitkeep以外は無視する設定を記入
    tmp/*  
    !.gitkeep

git管理から除外する(.gitignore)

既にgit管理下にあるファイルをgit管理から除外する

  • 参考 : http://d.hatena.ne.jp/hkobayash/20130416/1366129434
  • 方法 assume-unchanged
    • #無視
      git update-index --assume-unchanged [ファイル名]
    • #無視解除
      git update-index --no-assume-unchanged [ファイル名]
    • 現在の設定確認
      git ls-files -v
      h hoge.txt    # 小文字だと設定ON
      H huga.txt
  • 方法 skip-worktree
    • #無視
      git update-index --skip-worktree [ファイル名]
    • #無視解除
      git update-index --no-skip-worktree [ファイル名]
    • 現在の設定確認
      git ls-files -v
      S hoge.txt    # ステータスSだと設定ON
      H huga.txt
  • ,鉢△琉磴
    • ローカル、リモートともに編集中でgit pullした場合
      • ローカルの変更は破棄されて、リモートの状態を取り込む
      • ローカルの変更を保持し、リモートの状態を取り込まない
    • ローカル編集中でgit reset --hardした場合
      • ローカルの変更は破棄
      • ローカルの変更を保持

一部のサブディレクトリだけをcheckoutする

  • git sparse(まばらなの意)で可能

最初にcloneする方法

  1. git cloneでローカルリポジトリ作成
    git clone <リポジトリURL>
  2. sparsecheckout を有効にする
    git config core.sparsecheckout true
  3. チェックアウトする対象のディレクトリ、またはファイルを .git/info/sparse-checkout に記入
    echo I_want/this_folder/ > .git/info/sparse-checkout
  4. 下記コマンドを実行。ツリー情報を読み込んでindexにマージするらしい。
    git read-tree -m -u HEAD
  5. チェックアウトする対象を 増やす場合は、git/info/sparse-checkout に追記し、git read-treeを再実行
    echo I_forget/this_folder/ >> .git/info/sparse-checkout
    git read-tree -m -u HEAD

最初にcloneしない方法

  1. 空の Git リポジトリとして初期化
    git init
  2. sparsecheckout を有効にする
    git config core.sparsecheckout true
  3. リモートリポジトリの URL を origin として登録
    git remote add origin <リポジトリURL>
  4. チェックアウトする対象のディレクトリ、またはファイルを .git/info/sparse-checkout に記入
    echo "child/*" > .git/info/sparse-checkout
    • ディレクトリの場合は''最後にスラッシュをつけること'。'ないと、以下のエラーが発生する
      error: Sparse checkout leaves no entry on working directory
  1. 好きなブランチを pull (checkout) する
    git pull origin master

ブランチ管理

ブランチ作成 + リモートにpush

  • (通常)マスターブランチをもとに開発ブランチ作成
    git branch develop
    git checkout develop
    • 上記を一括で行う場合
      git checkout -b develop
  • 作成した開発ブランチをリモートブランチにpush
    git push origin develop

リモートのブランチをローカルにcheckout

  • リモートからブランチを取得
    git branch develop origin/develop
  • checkoutと同時にそのブランチに移動する場合
    git checkout -b develop origin/develop
  • 以下は現在いるローカルブランチにマージされるので、期待する作業でない場合はやってはいけない
    git pull origin [develop:]develop

マージ

  • developブランチの内容をmasterにマージ
    git checkout master
    git merge develop

コマンド

git status

git管理外ディレクトリ配下も表示

  • オプションなしのgit statusは、git管理外のディレクトリの配下は表示されない
    $ git status                                      
    On branch master
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
    
           dir/
    
    nothing added to commit but untracked files present (use "git add" to track)
  • -u オプションで管理外ディレクトリ以下のファイルも表示可能
    $ git status -uall # allはデフォルトなのでなくてもよい
    On branch master
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
    
           dir/dir2/huga.txt
           dir/hoge.txt
    

簡易版表示

  • -sで簡易表示
  • ステータス表示は、行頭から[ XY ]の二文字で表示される
    • X : git add した後のステータス (indexのステータス)
    • Y : git add する前のステータス (workツリーのステータス)
      $ git status -su
      XY
      A  dir/hoge.txt  # git管理外のファイル。git addした状態
       M hoge.txt      #  git管理下のファイルを修正。git addはまだしていない
      M  huga.txt      #  git管理下のファイルを修正。git addしている状態
      ?? dir/dir2/huga.txt # git管理外のファイル。git addしていない状態

ファイルを特定のリビジョンに戻す

git checkout <コミットID> <ファイル>

リモートから特定のブランチを指定してclone

git clone -b <ブランチ名> <URL>

差分ファイルをアーカイブ(svn export + zip)

ログ関連

トピックブランチのログのみ表示

ログにファイル名を表示する


リモートリポジトリの削除

  • リモートのfooブランチを削除する場合
    git push --delete origin foo
  • または
    git push origin :foo

git add時の改行コード変換のWARNを抑止

  • WIndowsでgitを使うとよく出る。以下で、改行コードの変換を無効にする
    git config --global core.autoCRLF false

リポジトリ配下のファイルを編集後、git addをスキップしてコミット

  • 「-a」オプションでgit addをスキップ可能
    git commit -a -m "edit hoge.txt"
  • なお、リポジトリ管理外のファイルは「-a」オプションを使用しても、無視される(git addが必要)

gitでのsvn revert

  • 全体を戻す場合
    git reset --hard HEAD
  • ファイルを指定して戻す場合
    git checkout [HEAD] <PATH>

SVNコマンドとの対応


リポジトリをHTTPで操作(clone push等)できるよう設定

Smart HTTPとは?

  • HTTPのプロトコルを利用しながら、sshや、gitのように効率のよい転送を実現するもの(っぽい)。gitインストール時に格納されているCGIスクリプトがエンジンを担ってそう。

ベアリポジトリ作成

shishimaru@v-cent65% sudo mkdir -p /home/git
shishimaru@v-cent65% cd /home/git
shishimaru@v-cent65% sudo git init --bare --shared myproject.git

Apache設定

  • HTTPでローカルからpushすることになるので、オーナーをapacheに変更しておく
    shishimaru@v-cent65% sudo chown -R apache:apache /home/git
  • BASIC認証用のパスワード作成
    shishimaru@v-cent65% htpasswd -c /home/git/.htpasswd shishimaru
    New password:
    Re-type new password:
    Adding password for user shishimaru
  • /etc/httpd/conf.d/git.confを作成
    SetEnv GIT_PROJECT_ROOT /home/git
    SetEnv GIT_HTTP_EXPORT_ALL
     
    ScriptAlias /git /usr/libexec/git-core/git-http-backend
     
    <locationMatch "/git">
      AuthType Basic
      AuthName "Git Area"
      AuthUserFile /home/git/.htpasswd
      require valid-user
      Order allow,deny
      Allow from all
    </locationMatch>
  • GIT_PROJECT_ROOT
    • リモートリポジトリのディレクトリパスを指定。
      • /usr/local/git/test.git がリポジトリのパスだったら /usr/local/git  と記述
  • GIT_HTTP_EXPORT_ALL
    • 設定しないと、クライアントからのアクセスは読み込み専用になり、読み込めるのは git-daemon-export-ok ファイルが保存されたリポジトリだけになる
  • ScriptAlias?
    • gitのCGIディレクトリを指定する。どこにGitをインストールしたかで格納場所も変わるので、locate等で確認すること
      shishimaru@v-cent65% sudo locate git-http-backend 
      /usr/libexec/git-core/git-http-backend
    • エイリアス名の最後に「/」はつけないこと。つけるとアクセス時Not Foundエラーになる

git clone時の注意

nginx版

Webブラウザから閲覧する設定

GitWeb?

GitWeb?概要

  • Subversionのように、Webブラウザからリポジトリを閲覧できる
  • ファイルの構成・中身だけでなく、ログも見れる

構築

  • 本体インストール
    shishimaru@v-cent65% sudo yum install -y gitweb
  • 本来、以下のような設定で、/etc/httpd/conf.d/git.confがインストールされるが
    Alias /git /var/www/git
    
    <Directory /var/www/git>
      Options +ExecCGI
      AddHandler cgi-script .cgi
      DirectoryIndex gitweb.cgi
    </Directory>
  • すでに自前でgit.confを作成していたので、git.conf.rpmnewというファイル名で上記が作成されていた。
  • また、上記Aliasの「/git」はすでにHTTPで利用する設定で使用していたので、git.conf.rpmnewはすべてコメントアウトして、以下のように自前git.confに設定を追加した。
    #------------------------------------
    # HTTPアクセス用の設定(元々の自前設定)
    #------------------------------------
    SetEnv GIT_PROJECT_ROOT /home/git
    SetEnv GIT_HTTP_EXPORT_ALL
    
    ScriptAlias /git /usr/libexec/git-core/git-http-backend
    
    <locationMatch "/git">
      AuthType Basic
      AuthName "Git Area"
      AuthUserFile /home/git/.htpasswd
      require valid-user
      Order allow,deny
      Allow from all
    </locationMatch>
    
    #------------------------------------
    # ここからgitweb用の設定 (追加分)
    #------------------------------------
    
    # ↓ Alias名をかぶらないようにgitwebに変更
    Alias /gitweb /var/www/git
    
    <Directory /var/www/git>
      Options +ExecCGI
      AddHandler cgi-script .cgi
      DirectoryIndex gitweb.cgi
    </Directory>
  • gitwebの設定。ブラウザ閲覧したいリポジトリの親ディレクトリを指定。
    shishimaru@v-cent65% sudo vim /etc/gitweb.conf
    
    our $projectroot = "/home/git";
  • 以上で、http://<サーバ>/gitwebにアクセスすると見れるはず

Windowsクライアント環境セットアップ

Git for Windows (msysGit)

  • 昔はmsysGitと呼ばれていた。Git Bashがインストールされる
  • Admin権限なしでインストール可能。
  • TortoiseGit?を利用する前提ソフトでもある。

TortoiseGit?

  • TortoiseSVNのgit版。
  • 要Admin権限

リモートリポジトリのブランチをローカルリポジトリに取得

  1. masterブランチでpull (リモートのブランチ情報の取得)
  2. 右クリック → TortoiseGit? → Swich/Checkoutで切り替え可能

改行コード変換無効

push時のユーザ名・パスワードの省略

HTTP(S)の場合

  • $HOME/.netrc (Windowsの場合 C:/User/<USER>/_netrc)に以下を記述
    machine 192.168.0.1
    login <USERNAME>
    password <PASSWORD>
    machine 192.168.0.2
    login <USERNAME>
    password <PASSWORD>

逆引き

GitLab?

SVNからGitへの移行

PKGインストール

  • RHEL6.3には標準でgit-svnパッケージが存在しない(オプショナルPKGが必要だが、外部接続(+サブスクリプションもいる?)が必要で今回はNG)ので、以下から、PKGをダウンロード
    • https://mirror.netcologne.de/oracle-linux-repos/ol6_latest/getPackage/
      • git-svn-1.7.1-2.el6_0.1.noarch.rpm
      • subversion-perl-1.6.11-7.el6.x86_64.rpm (依存PKG。無いと、インストール時に、perl(SVN::Core)が無いというエラーが発生する)
        ↑ subversionパッケージとリリース番号が一致するものをインストールすること。一致していないとたぶんインストールできない。
  • あとはyumでrpmを指定してインストール
    yum install git-svn-1.7.1-2.el6_0.1.noarch.rpm

移行手順概要

  1. git svn cloneでSVNからgitリポジトリ作成
    git svn clone -s --no-follow-parent --prefix=svn/ <SVN-URL>
  2. SVNのブランチ配下のディレクトリがgitのリモートブランチとして作成されているので、ローカルに作成
    • リモートブランチ一覧確認
      git branch -r 
    • ローカルブランチ作成(リモートブランチの数だけ実施)
      git branch <ローカルブランチ名> <リモートブランチ名>
  3. SVNのtag配下のディレクトリが、gitのリモートブランチに、tags/<ディレクトリ名>で作成されているので、これをgitのタグ付けする
    • リモートブランチ(タグ)一覧確認
      git branch -r | grep tags
    • git tag <ローカルタグ名> <リモートブランチ(タグ)名>
  4. ベアポジトリに反映
    • ベアリポジトリ作成(別ディレクトリで作業) git init --bare --shared <ベアポジトリURL> <ベアリポジトリディレクトリ>
    • 上記リポジトリをローカルに登録
      git remote add origin <ベアリポジトリURL>
    • ブランチ(master含む)をpush
      git -u push origin --all
    • タグをpush
      git push origin --tags

RPM