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したファイルを表示する

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だとパスワード無しの鍵を使う?

コミット

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

リセット

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

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

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

clean

マージ

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は簡潔表示(非追跡対象のファイルは「?? ファイル名」で表示)

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 -w   # ファイル内のスペースの違いを無視、改行コードの違いも無視
git diff -b   # ファイル内のスペースの数の違いを無視、改行コードの違いも無視
git diff --name-only    # 差分のあったファイルのファイル名だけを表示

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

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ブランチにあるコミットのログを表示

行が追加・削除されたコミットを調べる(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 '検索文字列'
  ファイル名を先頭に、行番号を行頭に表示して、検索文字列を検索する。検索文字列がマッチした
  とき、その行の前後各3行を表示する。
  作業ディレクトリ内で、カレントディレクトリ以下の追跡対象のファイルについて検索される。
  他のオプション
    -w  単語境界での検索
    -F  正規表現を利用しない
    -l  マッチしたファイル名だけ表示
git rev-list {--all|ブランチ名} | xargs git grep '文字列'
  すべてのブランチか、指定したブランチについて、検索をする
git grep -l 文字列 | xargs sed -i'' -e 's/文字列/置換文字列/g'
  カレントディレクトリ以下のファイルで、文字列、を含むファイルに対して、文字列を置換文字列
  に置き換える。
  なお、sedのオプション -i'' で検索されたファイルを直接書き換えて文字列置換をしている。
  -i'.old' とすると、置換前のファイルは、ファイル名.old でバックアップがとられる。
git grep 文字列 [タグ|SHA1]      # 該当プロジェクトで文字列検索

branch

git branch -a          #ローカルにある◯/◯のリモートブランチと、ローカルリポジトリのブランチをすべて表示
git branch ブランチ       # ブランチを作成
git branch -vv            # ブランチを表示
git branch -m 古いブランチ名 新しいブランチ名  #ブランチ名を変更する
git branch -m 新しいブランチ名                 #現在のブランチ名を変更する
git branch -d ブランチ            # ブランチを削除(ローカルのブランチ)
リモートリポジトリのブランチを削除し、ローカルのブランチも削除する
  git push origin --delete nwp2
  または git push origin :nwp2
  または git push origin :refs/heads/nwp2
次に、git fetch する(ローカルにあるその◯/◯のリモートブランチも自動で削除される)。
(備考)
・pullやcloneされた別のリポジトリでは、その人が消さない限りそのまま残る。消されたリモートブランチを
もつその人は、pushするとリモートリポジトリのブランチは再度作られる。
・detached branch(ブランチ名の付いていないブランチのようなもの)は、git logには出てこない。リポジトリに
残っていると思うが、どのように検索できるのか?

ローカルにある◯/◯のリモートブランチを削除する(あまり使わないだろう)
  git branch -d -r originfuji/masterfuji    #-dの代わりに -Dとするとマージしていなくても削除する
 (リモートにあるそのリモートブランチが削除されていなければ、fetchすると再度、〇/〇は作成される)
git branch --merged       # 現在作業中のブランチにマージされたブランチのリストを表示
git branch --no-merged    # 現在作業中のブランチにマージされていないブランチのリストを表示
git branch ブランチ1 リモートリポジトリ/ブランチ2    # リモートリポジトリ/ブランチ2を追跡
                                                       # するブランチ1を作る
git branch --set-upstream=リモートリポジトリ/ブランチ2 ブランチ1  # リモートリポジトリのブランチ2を追跡
                                                                    # するようにブランチ1を設定する

--set-upstream の省略形は -u である。

fetch

git fetch --all   # 登録されている全てのリモートリポジトリから最新情報を取得する
git fetch --tags  # リモートリポジトリにあるタグも取得する
git fetch [リモートリポジトリ] [ブランチ]  # リモートリポジトリから最新情報を取得する

pull

git pull [リモートリポジトリ]    # fetchし、mergeする(pull=fetch+mergeに相当)

push

git push [リモートリポジトリ] [ブランチ] [--tags]
    # 競合が発生した場合は pushはできない(pullして競合解決してから 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 -d タグ名     #タグ名を削除する
git show タグ名       #タグ名の情報を表示

git fetch --tags   #リモートリポジトリのタグを取得する
git push --tags                      #リモートリポジトリに無いタグを、全て送る(タグだけ送る)
git push --delete リポジトリ タグ名  #リポジトリ(originなど)のタグ名を削除

checkout

git checkout {SHA1|タグ|masterなど}    # 指定のものをチェックアウトする。
                       # ブランチ名(masterなど)ではなく、SHA1(ハッシュ値)を指定した時、detached HEADになるが、
                       # 普通どおり修正してコミットできる(ブランチ名を新たにつける方が取り扱いやすい)。
                       # 追跡対象外のファイルなどは、そのまま残される。
git checkout --track リモートリポジトリ/ブランチ    # git checkout -b ブランチ リモートリポジトリ/ブランチ と同じ。
                       # 作成されたブランチはリモートブランチ(追跡ブランチ、上流ブランチ)を追跡するように設定される。
git checkout -b ブランチ {タグ|リモートリポジトリ/ブランチ}    # -bで指定するブランチを作成後、移動する。
                       # タグがあれば、その所にブランチを作る(ただしコミットするとブランチは進む。タグは動かない)。

その他のコマンド等

gitk    # GUIツール
git help コマンド名
git diff差分はそのままでパッチファイルになっている。
また、パッチファイルを使って、リダイレクションでパッチをあてることが出来る。
patch [--dry-run] -p1 < パッチファイル    #パッチファイルをあてる場合
                                          #--dry-runは何が行われるかを表示するだけ。
$ git push
(gnome-ssh-askpass:hogehoge): Gtk-WARNING **: cannot open display:
error: unable to read askpass response from '/usr/libexec/openssh/gnome-ssh-askpass'
Username for 'https://github.com':
などと、表示される場合の対応。

- 無視して、つづけて問題無い。
 (GUI環境で無いために、パスワードキャッシュがうまく動かなかったらしい)

- unset SSH_ASKPASS
  をすると表示されなくなる。

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