howto/git

一行メモ

はじめてのGit

こちらへ howto/git/forthefirsttime

リマインド注意事項

The entire Pro Git book, written by Scott Chacon and Ben Straub

https://git-scm.com/book/ja/v2

ここからダウンロード(2021/04/15)したPDF版のファイル (ただしそのままでは不具合があるようだったので、macOSのプレビューで開いてから再度PDFで保存し作成した)。 2nd Edition (2014) のファイルです。 なお、旧版はDownloadsメニューにあるらしい。

このPDFは Scott Chacon and Ben Straubにより書かれたものであり、 ライセンスは CC BY-NC-SA 3.0です。

以下は古いもの。

ファイルの追加・名前変更・削除

ファイルを追加(追跡対象にする)

例)
git add .         # カレント以下のファイル(ディレクトリ含む)をステージに追加する
git add ファイル  # ファイルをステージに追加する
git add -u        # 追跡対象のファイルで修正があったものをステージに追加する

ファイル名変更

mv 変更前のファイル名 変更後のファイル名
git add 変更前のファイル名  #削除した(無くなった)ことをステージに追加する
git add 変更後のファイル名
#gitとしては、削除されて、新しい名前で追加する形の操作となっている

または
git mv 変更前のファイル名 変更後のファイル名

ファイルの削除

rm ファイル名
git add ファイル名
#gitとしては、削除したファイル名、無いファイル、を追加する形の操作となっている

または
git rm ファイル名

削除するファイルが、ステージに載っている場合は --cachedオプションが必要
git rm --cached ファイル名  #ステージから削除し、ファイルを削除し、無いファイルを追加する形

ファイルの変更維持

ファイルを更新したが、その更新を維持したままにする(git pull等で更新されないようにする)
git update-index --skip-worktree    ファイル名  # 更新されないように登録する

git update-index --no-skip-worktree ファイル名   # 登録を解除する

git ls-files -v | grep  ^S    # skip-worktreeしたファイルを表示する

git commit, reset, clean, merge

コミットするときの注意点

    ⇒ むずかしいのでほどほどで対応すればよい。

    ⇒ コミットメッセージは英語でする。日本語は使わないこと。

最初設定すると良いこと

git config --global user.name   "yourname"   # 実行すると ~/.gitconfigに保存される
git config --global user.email  "youremail"  # --global無しだとリポジトリ毎の.git/configに保存される
git config --global core.editor emacs
git config --global push.default simple      # simple(デフォルト)、matching(2.0以前のデフォルト)

git config --global credential.helper 'cache --timeout=1800'  # 数分間だけ認証をキャッシュする。
                                                              #httpsのみ?sshだとパスワード無しの鍵を使う?

commit

git commit -m 注釈     # ステージ済みをコミットする
git commit -a -m 注釈  # 追跡対象(のみ)をステージして、コミットする

reset

git checkout -- ファイル名   #作業ディレクトリのファイルが、チェックアウト時点に戻される
                             #(ファイルに変更があれば、失われる)

git reset HEAD ファイル名    #ステージのファイルが削除される形
                             #(作業ディレクトリのファイルは、何もされない)

git reset --hard    #現在のブランチを、チェックアウトの時点まで取り消す
                    #(ファイルに変更があれば、失われる)

clean

merge

dry-run的なことをして確認後、マージをコミットする手法 ★お薦め

現在のブランチに、指定のブランチをマージ
$ git merge --no-commit --no-ff [リモートリポジトリ/]ブランチ
            #コミットしない、fast forwardでもコミットしない。
これで、マージされた結果はステージに載るので、
$ git diff --cached
で結果を確認できる。コンフリクト(競合)していたらその旨が git merge 時に出るので手動解決する。
そして、
(a) このマージを取り消したければ、git merge --abort をする。
(b) そのままコミットしたければ git commit -m "merge branch hoge1 into hoge2" をする。
    又は git merge --abort 後に git merge [リモートリポジトリ/]ブランチ をしてもよい。

作業ブランチへのマージの仕方(まとめ)

       +------>o fixブランチ
       |
------>o masterブランチ
       |
       +------------->o----> 作業ブランチ
                       ~~~~~
                       未コミット部分A
       o 印はコミット

ブランチの分岐が上図のようにあり、
作業ディレクトリのブランチに fixブランチをマージするには、
次の(1)-(4)のいずれかの方法でできる。

作業ブランチをコミット済みの状態にしておき、(2)の方法でコミット
するのがいちばん素直だろう。
(fixがmasterの進んだコミットであっても同じ)

(1)
git merge origin/fix
これは自動的にコミットされる。
たぶんA部分があればエラーとなる? もしくは、A部分もコミットされる? fixに関係
するファイルだけか?
コンフリクトしたら作業ディレクトリのファイルにその内容が入る。

(2)
git merge --no-commit --no-ff origin/fix
自動的にコミットしない。
コンフリクトしたら作業ディレクトリのファイルにその内容が入る。
確認後、
git merge --abort
で取り消すか(取り消してから(1)でマージしてもよい)、または、
コンフリクトがあれば修正して(無ければそのままで)、
git commit -m "hogehoge"
する。
(なお、コミットする前にはコミットするファイルを取捨選択もできる)。

(3)
git cherry-pick SHA1
fixのコミットのSHA1をマージする。master--->fixの間に複数のコミット
があれば順に全てに対してこのコマンドでマージする。
たぶんコンフリクトしたら作業ディレクトリにその内容が入る。

(4)
git stash
--skip-worktreeしたファイルは無いことが望ましい。
git merge origin/fix をする(または (1)-(3)のいずれかでもよい)。
git stash pop
たしか、コンフリクトしたら作業ディレクトリのファイルにその内容が入る。
そして stashは消されずに残る。

リポジトリの作成・移動

ローカルリポジトリ

・作成方法1(新規作成)

cd 作業ディレクトリ
git init
・作成方法2(リモートリポジトリのクローン)

git clone リモートリポジトリ [作業ディレクトリ]
  # リモートリポジトリは [ssh://[user@]host.xz[:port]]/path_to_repo.git などのurlで指定する。
  # 自動的に、origin という登録名でurlが登録され、リモートブランチ(origin/master)を追跡するブランチ master が作られる。
  # 作業ディレクトリを省略すると、リモートリポジトリのディレクトリ名(ディレクトリ名.gitの.gitの前の部分)となる。
  # 作業ディレクトリを指定する場合は、既存のディレクトリを使う場合はそれが空ディレクトリでなくてはならない。

ベアリポジトリ

・作成方法1

cd ディレクトリ.git  # 拡張子を慣習的につける
git init --bare

空のリモートリポジトリ(ベアリポジトリ)にpushする(新規のベアリポジトリにファイルを追加する)例

git add ファイル
git remote add origin リモートリポジトリ  # リモートリポジトリを登録名originとして、登録する
git remote -v ; git branch -vv
git commit -m "注釈"
git push --set-upstream origin master     # --set-upstreamは現在のプランチの追跡先を、origin/masterとする設定を登録する

リモートリポジトリ自体の移動、それを追従しているリポジトリでの設定の変更

リモートリポジトリの移動自体は単にまるごとディレクトリを移動するだけである。
これに追従しているリポジトリは
git remote set-url origin 新しいリモートリポジトリ
をして、登録名の内容を上書き更新する(originを消してから作り直してもよい)。

又は、originを作り直す場合は
git remote rm origin                   # リモートリポジトリの登録名originを削除
git remote add origin リポジトリのURL  # URLでリモートリポジトリを登録名originで作成

リモートリポジトリの登録、変更、削除

git remote add リモートリポジトリの登録名 リモートリポジトリのurl
git remote rename リモートリポジトリの変更前の登録名 リモートリポジトリの変更後の登録名
git remote rm 削除するリモートリポジトリの登録名
git remote set-url origin 変更後のリポジトリのURL  # URLの上書き変更
git remote [-v]  # リモートリポジトリの一覧表示

新しいブランチを作り、追いかける手順の例(よく使う)

ローカルにブランチを作り、リモートリポジトリにpushする

作業ディレクトリやステージは commit,push済であるとする
$ git branch nwp      # 現在の状態で、ブランチnwpを作成
$ git checkout nwp    # ブランチnwpに移動
なお、ここの段階でファイルを変更して add,commitをしても良い。
$ git push --set-upstream origin nwp  # リモートリポジトリoriginのブランチnwp(作成される)に pushする。
                                      # nwpは、origin/nwpを追跡するように設定される(オプション
                                      # --set-upstreamによる)。

リモートリポジトリで、新たに作成されたブランチnwpを追いかける

作業ディレクトリやステージは commit,push済であるとする
$ git fetch --all --tags
$ git checkout --track origin/nwp  # リモートリポジトリoriginのブランチnwpを追従するローカルのブランチnwp
                                   # を作成し、チェックアウトする。
                                   # git checkout -b nwp origin/nwp  でも同じ。
(例)同じリモートリポジトリoriginを上流にもつリポジトリAとBがあるとする。 Aで新しいブランチnbを作成し、originにpushした。 Bでpushされ作成されたブランチnbを追従するように、ブランチnbを作成する。 すると、AとBとの間でファイルの同期のようなことが出来る。 すなわち、Bのnbで変更した内容を、Aのnbに取り込んだり、その逆が可能。 なお、AとBとで同時に同じファイルの同じ箇所に対して異なる修正をした場合には、コンフリクト(競合)が発生する。 この場合はマージ作業を行う。

gitコマンド

status

git status [-s]    # -sは簡潔表示(非追跡対象のファイルは「?? ファイル名」で表示)
.gitignore ファイル
  このファイルを使って無視するファイルを指定できる(非追跡対象をstatusで表示させなくする等)。
  再帰的にディレクトリ階層に適用される。
  利用できる正規表現は git help gitignore や man gitignore を見よ。
  (例)作業ディレクトリに以下の内容で .gitignoreを置く
        *.x
        *.o
        *.a
        *~

diff

git diff [--] [ファイル]           # 作業ディレクトリとステージの比較。ファイルを指定するとそのファイルだけ比較
git diff --cached [--] [ファイル]  # ステージとコミット済みの比較。ファイルを指定するとそのファイルだけ比較
                                   # 曖昧さがある場合は、ファイル名の引数の前に -- を付ける。
                                   # ファイルには、ディレクトリ名を与えることもできる。
git diff A B   [--] [ファイル]  # 差分をみる。AやBは SHA1や、ブランチ、タグなどで指定
git diff A..B  [--] [ファイル]  #     〃
git diff A...B [--] [ファイル]  # AとBとの共通の親と, Bの差分
(例)
git diff master..origin/master   # リモートリポジトリ(origin/master)との差分をみる
                                 # origin/masterの位置は fetchなどで更新されるので、
                                 # しばらく fetchやpullをしていない場合には位置が古い場合も生じうる
git diff A:file1 B:file2    # Aのfile1とBのfile2の比較
git diff -U20 # 違いがあった所の前後20行を含めて差分を出力する
git diff -w   # ファイル内のスペースの違いを無視、改行コードの違いも無視
git diff -b   # ファイル内のスペースの数の違いを無視、改行コードの違いも無視
git diff --name-only    # 差分のあったファイルのファイル名だけを表示

git diff --name-status  # 差分のあったファイルのファイル名と、変更か追加か削除かも表示
                        # git status -s と同じ?

空白に関する警告を表示する(コミット前に予め確認すると良い)

$ git diff --check
作業ディレクトリの変更について、空白に関する警告を表示する。
デフォルトでは以下の場合に警告する(core.whitespaceの設定で変更可、詳細はググれ)。
  o 行末に空白がある
  o 空白を含む空行がある
  o ファイルの末尾に空行がある
  o タブの次に空白がある

show

git show オブジェクト[:ファイル]  # コミットやその内容(ファイル)を表示する。
                                  # オブジェクトは SHA1や、ブランチ、タグなどで指定
                                  # :ファイル 特定のファイルのみ表示

log

コミットログを表示する
git log -5 --oneline --decorate --graph --all [--stat] [-p] [レンジ] [--] [ファイル]
                                                             # --graphにより図形表示される
                                                             # --author=パタン でuser.nameの選択ができる
                                                             # --decorateによりHEADの位置がわかる
                                                             # -pはソースの差分が出る。
                                                             # --statはサマリーが出る。
                                                             # -5は 5件だけ表示

git log --grep hogehoge  #ログ内容を検索

git log -p -S'hogehoge' file  # コミットの中で、fileのhogehogeを含む行が追加or削除された
                              # コミットを検索する。
                              # -pオプションがあるのでそのコミット時の差分も表示(マージは対象外)。
(その他のオプション)
git log --since="50 minutes ago"    # 50分前からのログのみ表示

git log --no-merges issue54..origin/master    #ログのフィルター記法(レンジで指定している)
 #origin/masterには含まれるが、issue54には含まれないコミットのログだけを表示

git log contrib --not master  # masterに無くcontribブランチにあるコミットのログを表示

git log のフォーマット指定(log)

git log --oneline --decorate --graph --all --pretty=format:'%C(auto)%x09%h %d %s %C(blue)%cd %an%C(reset)' --date=short
  %C(色名)  文字の色を指定。autoだと項目により自動で色付けされる。resetは前の状態に戻す。
  %x09  タブ
  %h    sha1(ハッシュ値)
  %d    注釈
  %cd   日付。日付のフォーマットは別途 --date=shortで与えている。
  %an   コミットした人
  --date=iso だと "2015-03-21 16:24:43 +0900" となる。他の指定は git help log を見よ。

~/.gitconfig に次のものを入れておくと、git mylog --all とできる。
[alias]
   mylog = log --oneline --decorate --graph  --pretty=format:'%C(auto)%x09%h %d %s %C(blue)%cd %an%C(reset)' --date=short

行が追加・削除されたコミットを調べる(log)

git log --cc --all -S"h5py.get_config().default_file_mode = 'a'" misc.py
  --ccで各コミットのdiff(実際はパッチ)をとる(マージコミットも対象とするために -pでない方がよい)
  -Sで検索にヒットしたコミットだけ表示する

コミットのSHA1やコミットメッセージがわかるので、
git show 287658 や、git log 287658 、
gitkの Find欄にそのメッセージを入れて、コミットを検索表示できる(親や子のSHA1がわかる)

blame

git blame [-C] -L n,m file    # fileに対して、n~m行目の最後のコミットをリストアップする
                              # -Cがあるとfile名の変更も追跡してコミットを探してくれる
                              # 行は1から数える。

(例、どのコミットで追加されたものかを調べてる)
$ git blame -C -L 22,24 makefile
dfa94f47 (okazaki,i 2022-09-10 17:07:28 +0900 22) #DOPT = -O3 -ffast-math
1e84d5f5 (okazaki,i 2018-03-19 20:13:09 +0900 23) DOPT = -Ofast
059d6a13 (okazaki,i 2023-03-17 22:14:06 +0900 24) #DOPT = -g -Ofast
(他)
gitに bisectというものもあり(二分探索によるデバッグ支援)。
git log -p -S も見よ。

grep

git grep --heading --line-number -3 '検索文字列' [sha1など]
  ファイル名を先頭に、行番号を行頭に表示して、検索文字列を検索する。検索文字列がマッチした
  とき、その行の前後各3行を表示する。
  作業ディレクトリ内で、カレントディレクトリ以下の追跡対象のファイルについて検索される。
  sha1などを指定するとそこで文字列検索する。
  他のオプション
    -w  単語境界での検索
    -F  正規表現を利用しない
    -l  マッチしたファイル名だけ表示
git rev-list sha1など [-- パス] | cut -c -7 | xargs git grep '文字列'
  コミットのsha1やブランチ名などを指定(--allも可)し、そこから全てのコミットを遡って、
  文字列を検索する? パスを指定すると限定できる?
  なお、git grep の結果で、40桁のsha1の代わりに 7桁で出力させるため cut -c -7 をはさんでいる。

(例)
git rev-list --all | cut -c -7 | xargs git grep --heading --line-number -10 'rs+1'
git grep -l 文字列 | xargs sed -i'' -e 's/文字列/置換文字列/g'
  カレントディレクトリ以下のファイルで、文字列、を含むファイルに対して、文字列を置換文字列
  に置き換える。
  なお、sedのオプション -i'' で検索されたファイルを直接書き換えて文字列置換をしている。
  -i'.old' とすると、置換前のファイルは、ファイル名.old でバックアップがとられる。

branch

git branch -vv       #ブランチを表示
git branch -a        #リポジトリにある全てのブランチを表示(リモートの◯/◯とローカルの◯ 両方)
git branch ブランチ                            #ブランチを作成
git branch -m 古いブランチ名 新しいブランチ名  #ブランチ名を変更する
git branch -m 新しいブランチ名                 #現在のブランチ名を変更する
git branch --merged       # 現在のブランチにマージされたブランチのリストを表示
git branch --no-merged    # 現在のブランチにマージされていないブランチのリストを表示
(使い終わったブランチはだいたい削除されるので、あまり意味はないかも)
git branch -d     hoge         #ローカルリポジトリのブランチhoge(ローカルブランチ)を削除
                               #(予めhoge以外をカレントブランチにしておく) 

git branch -d -r  origin/hoge  #ローカルリポジトリのブランチorigin/hoge(リモートブランチ)を削除
                               #(リモートリポジトリでも削除していない場合、fetchで再度作成される)

git push origin --delete hoge  #リモートリポジトリoriginのブランチhogeを削除
または git push origin :hoge
または git push origin :refs/heads/hoge
(git fetch するとローカルリポジトリのリモートブランチは自動的に削除される?)
自分がブランチを消したとしても、cloneした他の人が使っているリポジトリでは、 その人が消さない限りその人のリポジトリには残る。 自分がリモートリポジトリのブランチを消したとしても、他の人が何らかのpushをすると リモートリポジトリに再度、自分が消したブランチが作成される。 (cloneした全員のリポジトリでブランチを消さないと、実質消すことはできない。)

リモートリポジトリのブランチを作成や追跡(branch)

リモートリポジトリにブランチが無い場合

ローカルリポジトリのローカルブランチを、リモートリポジトリに送ってブランチを作り、追跡するように設定
git push -u origin hogeB:hogeA  #hogeBブランチを、originのhogeAにpushする。
                                #-u により hogeBはorigin/hogeAを追跡するようにも設定される。
                                #(-uは--set-upstreamの短縮形)
git push -u origin hogeA:hogeA  #同じブランチ名のときは、このように書けて、また、
git push -u origin hogeA        #このようにも書ける(・これはよく使う・)

リモートリポジトリにブランチが有る場合

git branch hogeB origin/hogeA    #リモートリポジトリのブランチorigin/hogeAを追跡するブランチhogeBを作る

git branch --set-upstream=origin/hogeA hogeB  #リモートリポジトリのブランチorigin/hogeAを追跡するように
                                              #既存のブランチhogeBに設定をする
                                              #(hogeBを省略するとhogeAが使われる)

fetch

git fetch --all         # 登録されている全てのリモートリポジトリから最新情報を取得する
git fetch --all --tags  # 上記に加え、リモートリポジトリにあるタグも取得する

git fetch [リモートリポジトリ] [ブランチ]

pull

git pull [リモートリポジトリ]    # fetchし、mergeすることに相当

push

git push [リモートリポジトリ] [ブランチ] [--tags]
    # 競合が発生した場合は pushはできない(fetch, mergeし、競合解決してから pushする)
    # --tagsはタグもプッシュする

tag

git tag タグ    #タグを付ける

git tag [-a] タグ [SHA1など] [-m 注釈]  # タグを付ける
  # -aと-mで1行の注釈を入れれる。-aのみは注釈を入れるためにエディタが立ち上がる。
  # -sオプションで署名もできるらしい(詳しくは https://git-scm.com/book/ja/v2 の5章)
git tag  # すべてのタグを表示
git tag -d タグ名  #タグ名を削除する
git fetch --tags   #リモートリポジトリのタグを取得する
git push --tags                      #リモートリポジトリにタグを全て送る(タグだけ送る?)
git push --delete リポジトリ タグ名  #リポジトリ(originなど)のタグ名を削除

checkout

git checkout {ブランチ|タグ|sha1など}  #指定のものをチェックアウトする
  #非追跡対象のファイルなどは、そのまま残される。
  #sha1でチェックアウトした時、detached HEADになるが、普通どおり修正してコミット
  #できる(ブランチ名を新たにつける方が取り扱いやすい)。
git checkout -b ブランチ {リモートリポジトリ/ブランチ|タグ|sha1など}  #指定したものをチェックアウトし、
                                                                      #-bで指定したブランチを作成する
  #リモートリポジトリ/ブランチを指定した場合、
  #作成したブランチはリモートブランチ(リモートリポジトリ/ブランチ)を追跡するように設定される。

git checkout --track リモートリポジトリ/ブランチ  #git checkout -b ブランチ リモートリポジトリ/ブランチ
                                                  #と同じ
  #作成したブランチはリモートブランチ(リモートリポジトリ/ブランチ)を追跡するように設定される。

その他のコマンド等

gitk

gitk [--all] [ファイル]   # git log などのGUIツール

git help

git help コマンド名    #gitのオンラインマニュアル

パッチ

git diff差分はそのままでパッチファイルになっている。
パッチの当て方
patch [--dry-run] -p1 < パッチファイル    #--dry-runは何が行われるかを表示するだけ。

git config

git config [--global] -l    # .git/configを表示
git config [--global] -e    # .git/configを編集

表示の色変更(git config)

HEADなど(sha1の別名)

HEAD    #現在checkoutしているコミット(ブランチ等)のsha1を表す別名
HEAD^   #HEADのひとつ前のコミットを表す
HEAD^^  #HEADの前の前のコミットを表す
(sha1の数字を使っても同じことを表せる。なお gitkでは利用できないようだ。)
例)
$ S=91dc63f git diff ${S}^..${S} sample_H2mb64g64.inp

アーカイブを作る

git archive master --prefix='project/' --format=tar > git_master.tar  #masterブランチのアーカイブ
git shortlog --no-merges master --not master_20220310  #ショートログを表示
                                                       #masterブランチに対してタグmaster_20220310から
                                                       #のぶんを表示する

GitHub

不具合対応

tips

変更のあったファイルを emacsでいっきに開く

emacs `git diff --name-only`

変更があったファイルで、行末に空白があるものを調べる

#タグmaster_20200619から変更があったファイルのうち、拡張子がc,h,l,yのファイルについて
#行末にひとつ以上の空白があるもののファイル名を表示する
for f in ` git diff --name-only  master_20200619  | grep '\.[chly]$' `; do \
  echo ==== $f ====; grep ' \+$' $f > /dev/null; [ $? == 0 ] && echo $f ; done | grep -v ^====

変更があったファイルで、タブを含むものを調べる

#タグmaster_20200619から変更があったファイルのうち、拡張子がc,h,l,yのファイルについて
#タブを含むファイルのファイル名を表示する
for f in ` git diff --name-only  master_20200619  | grep '\.[chly]$' `; do \
  echo ==== $f ====; grep $'\t' $f > /dev/null; [ $? == 0 ] && echo $f ; done | grep -v ^====
                     #(注: ここで $'~' はbashの機能。$'\t'はエスケープしたタブ?)

HEADのsha1値と注釈を表示する

temp=`git rev-parse --short HEAD; git log -1 --pretty=%B` ; echo $temp

作業ディレクトリの変更の有無を表示する

if git diff --quiet >/dev/null 2>&1; then echo "--"; else echo "modified"; fi

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS