Friday, November 18, 2016

Memo of git usage ギット学習メモ

 最近、数多くのオープンソースプロジェクトはGitHubを使うようになっています。たとえば、人工知能で有名はTorchというプラットホームもその一つです。

 既存のものを壊す前に、まず自分でいろいろ試した方はいいので、github.comでアカウントを作り、gitコマンドを使い倒すことをお勧めします。

LinuxやUnix環境でコマンドだけを使う場合、まず以下のコマンドでユーザーインターフェース(GUI)を止めましょう。
$unset SSH_ASKPASS
そうしないと、例えばgit pushを実行すると、以下のエラーメッセージが表示され、コマンドが失敗します。
(gnome-ssh-askpass:28497): Gtk-WARNING **: cannot open display:
次には、必須のREADME.mdを作成してから、以下のコマンド群でサーバーに追加してみましょう。
git init
git add README.md
git commit -m "inital commit"
git remote add origin https://github.com/user_name/repository_name.git
git push -u origin master
但し、user_nameは自分が作成したアカウント名で、repository_nameは自分が作成したリポジトリ(repository)の名前です。また、git initは最初の時一回だけ実行することです。
push時は、UsernamePasswordが聞かれるので、アカウント作成時の同情報を入力すればOkです。

0.gitの作業環境モデル
 gitはworkspaceindexrepositoryという三つの「スペース」がある。repositoryはローカルとリモートとあり、リモートはいわゆるサーバで、全員共有するものである。前者のローカルのrepositoryは自分のところにあり、自分しか見えないものである。

 workspaceは作業場で、実際直接に編集や削除、新規追加できる場所である。

 indexはrepositoryにcommitするための場所で、workspaceで変更・追加したものを一旦こちらにaddしなければいけない。

  repositoryはファイルの履歴などを管理する場所であり、リビジョン管理の中心である。indexにあるものはcommitコマンドでこちらに反映する。

  ローカル環境で、あるリモートのURL<url>に略称(origin)を付けるには、
      $git remote add origin <url>
 ここでは、originというのは世間一般的に使われている略称で、混乱を恐れなければ、どんな名前でもよい。

 初めての作業としては、リモートリポジトリをクローンすること。
    $git clone <remote_git_url>

1.ブランチを作成・変更する
 以下のコマンドで、branchnameというブランチを作成し、そのブランチに切り替える。
      $git checkout -b <branchname>
 システムは、以下のメッセージを表示するはず。
      $Switched to a new branch 'branchname'
 但し、これだけでは、まだローカルにあるので、以下のコマンドでリモートに追加する
      $git push origin <branchname>
 以下のコマンドで、指定ブランチを削除する
      $git branch -d <branchname>
 但し、作業中の内容があるが、それでも削除したい場合、以下のコマンドで強制的に削除
      $git branch -D <branchname>


2.リモート・リポジトリからファイル・変更を取得・同期する
 あるブランチbranchnameのファイルを取得するには、
    $git fetch origin branchname
    $git checkout branchname
 間違って一つのファイルを消して、それを復元させたい場合(ただし、commit前)
    $git checkout <filename>

 リモートリポジトリから、あるブランチbranchnameの最新内容をローカルに反映するには、
    $git pull origin branchname

3.ファイルを追加・変更する
 以下のコマンドで追加・変更したファイルをindexに反映する
      $git add <add-or-changed-file>
 以下のコマンドでindexにある変更・追加のファイルをローカルのrepositoryにコミットする
      $git commit <add-or-changed-file> -m "my comment"
 ローカル・リポジトリを更新するには(つまり最新の内容をリモートから持ってくる)
      $git pull

 気を付けなければいけないのは、"add ."というコマンドです。
     $git add .
 というコマンドで、現在のディレクトリーの下にある変更ファイルをすべてindexに持っていきます!
 特にgitignoreファイルをちゃんと設定していないと、コンパイルした中間ファイルや、エディターが作成したバックアップファイルはすべてaddされる!「.gitignore」ファイルはブランチごとに元ますので、いつも同じものを無視してもらい時には、以下のように、グローバル用のignoreファイルを設定しよう。
      $ git config --global core.excludesfile [git_ignore_file_name]

 万が一やってしまった場合、つまり関係ないファイルをaddした場合、以下のコマンドでやり直せる。"."は現在のディレクトリの意味。
    $git reset .
 これで、indexにaddしたすべてのものを元(commit前)に戻せる

 git add した個別のファイルを元に戻すには
    $git reset HEAD -- $file

 commitしたばかりのものを取り消したい場合、以下のコマンド
      $git reset --soft HEAD~1

 新規ファイルをindexにaddしてほしくないときに、「-u」オプションを使おう。
      $git add -u

 リモートのブランチとの差分を確認するには、まずリモートのブランチをリストアップし、
      $ git branch -a
      * master
    remotes/origin/master
    remotes/origin/branch1
 それから、以下のコマンドを実行する
      $ git diff remotes/origin/branch1

 ローカルで変更したファイルを元の状態に戻すには
     $ git reset <file_name>
     $ git checkout <file_name>

4.ブランチにタグを付ける
 以下のコマンドでチェックアウトされているブランチにタグを付ける
      $git tag <tage_name>
 デフォルトでは、git push コマンドはタグ情報をリモートに送らないため、以下のようにリモートサーバーにプッシュする必要がある。
      $git push origin <tag_name>
 タグを削除するには
      $git tag -d <tag_name>
 リモートのタグを削除するには、上記のようにローカルのタグを削除した上に
      $git tag -d :<tag_name>

5.ブランチをマージする
  以下のコマンドで、チェックアウトされているブランチを指定ブランチ<branch_name>とマージできる
      $git merge <branch_name>
      $git push origin <branch_name>

6.公開鍵について
デフォルトでは、自分のルートの.sshの下にid_rsaという公開鍵のファイルを作るが、その属性は644だったりすると、以下のエラーになります。xxxはユーザー名です。
Permissions 0644 for '/home/xxx/.ssh/id_rsa' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
bad permissions: ignore key: /home/xxx/.ssh/id_rsa
id_rsaの属性を600にすれば問題がなくなります。

7.ローカルのcommit等の変更をすべて捨てて、リモートのもので置き換える
 何かの理由で、ローカルリポジトリにあるすべての変更(commitを含む)を捨てて、リモートリポジトリにある最新のものから再スタートしたい時に、以下のコマンドを実行する必要がある。
    git reset --hard @{upstream}

8.stashの中身を見るには
    git diff HEAD..stash@{0}

9.ローカルリポジトリにあるコミットをすべて破棄するには
        git pull --rebase

10.gitのindexファイル
  indexファイルのフォーマットは以下にリンクにある
  https://github.com/git/git/blob/master/Documentation/technical/index-format.txt
  indexファイルの内容を確認するには
    git ls-files

11.gitの環境変数
  Gitの内側 - 環境変数で詳しく説明されている

12.ローカルディレクトリにgitをインストールする
  Linuxマシンで管理者権限がなくてgitもインストールされていない場合、自分ホームの下にインストールすることはできます。バージョンは一例ですが、他のバージョンについてはhttp://git-core.googlecode.comで調べてください。/home/hoge/bin/localはインストール先です。
   gmakeの代わりにmakeを使う環境もあります。
  $ wget http://git-core.googlecode.com/files/git-1.7.11.3.tar.gz
  $ tar xf git-1.7.11.3.tar.gz
  $ cd git-1.7.11.3
    $ ./configure --prefix=/home/hoge/bin/local
    $ gmake
    $ gmake installl

13.git: 'submodule' is not a git command. See 'git --help'
 インストールしたバージョンによっては、submoduleコマンドが入っていないこともあり、"git submodule"コマンドを実行すると、上記のエラーになります。
 本人の場合は、git-all.noarchをインストールしたら、submoduleもインストールされました。

14.Gitの過去コミットから検索する
チェックアウトしているブランチで
git rev-list HEAD | xargs git grep '検索文字列'
ブランチ指定
git rev-list ブランチ名 | xargs git grep '検索文字列'
全ブランチから
git rev-list --all | xargs git grep '検索文字列'

15.二つのブランチの分岐点のコミットを検索する
git show-branch --sha1-name branch_A branch_B | tail -1

オプション指定
正規表現
git rev-list --all | xargs git grep -e '正規表現'
複数キーワードでAND,OR,NOT検索したい場合、
git rev-list --all | xargs git grep -e '検索文字列1' --and -e '検索文字列2'
これで、2つの検索文字列を同時に含む行が出力されます。--or, --not も一緒に使えます。
検索文字列を含む前後10行を表示したい場合。
git rev-list --all | xargs git grep -10 '検索文字列'
ファイル名を先頭に出力して、各行に行番号を出力する。
git rev-list --all | xargs git grep --heading --line-number -10 '検索文字列'

git -p file-name
コミットのすべてのDiffを見られます。

ちょっと場違いですが、リモートサーバーのディレクトリと同期を取りたいコマンドは以下の通りです。
rsync -avz username@lotus:/dir_name_on_server dir_name_local


参考リンク
[1] Git Branching Basic: Branching and Merging
[2] Git の基礎勉強 ~ Git によるバージョン管理 ~¶
[3] サルでもわかるGit入門~バージョン管理を使いこなそう~
[4] gitでアレを元に戻す108の方法
[5] Gitの過去コミットから検索するには

No comments:

Post a Comment