git diff eaad7c8 254b87b d3087fd #changes when merging git diff -U10 eaad7c8 254b87b d3087fd #changes when merging 違いが出るのはなぜか?
こちらへ howto/git/forthefirsttime
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 # 追跡対象のファイルで修正があったものをステージに追加する
例) find . -type d -empty -not -path './.git*' -exec touch {}\/.gitkeep \;
mv 変更前のファイル名 変更後のファイル名 git add 変更前のファイル名 #削除した(無くなった)ことをステージに追加する git add 変更後のファイル名 #gitとしては、削除されて、新しい名前で追加する形の操作となっている または git mv 変更前のファイル名 変更後のファイル名
rm ファイル名 git add ファイル名 #gitとしては、削除したファイル名、無いファイル、を追加する形の操作となっている または git rm ファイル名 削除するファイルが、ステージに載っている場合は --cachedオプションが必要 git rm --cached ファイル名 #ステージから削除し、ファイルを削除し、無いファイルを追加する形
git reset HEAD ファイル名 #ステージのファイルが削除される形
git checkout -- ファイル名 #作業ディレクトリのファイルが、チェックアウト時点に戻される
git reset HEAD ファイル名 #ステージのファイルが削除される形 git checkout -- ファイル名 #作業ディレクトリのファイルが、チェックアウト時点に戻される
ファイルを更新したが、その更新を維持したままにする(git pull等で更新されないようにする) git update-index --skip-worktree ファイル名 # 更新されないように登録する git update-index --no-skip-worktree ファイル名 # 登録を解除する git ls-files -v | grep ^S # skip-worktreeしたファイルを表示する
git ls-files -o #カレントディレクトリ以下で、追跡されていないファイルのリストを表示 git ls-files -o --exclude-standard #git ls-files -o のうち、.gitignoreで無視したファイルを除くリスト
⇒ むずかしいのでほどほどで対応すればよい。
⇒ コミットメッセージは英語でする。日本語は使わないこと。
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 commit --amend -m 注釈 # 直前のコミットを上書きする(直前のコミットをやり直せる)。 # ただし、push前であること。push後だと mergeが必要となるのでしないこと。
git checkout -- ファイル名 #作業ディレクトリのファイルが、チェックアウト時点に戻される #(ファイルに変更があれば、失われる) git reset HEAD ファイル名 #ステージのファイルが削除される形 #(作業ディレクトリのファイルは、何もされない) git reset --hard #現在のブランチを、チェックアウトの時点まで取り消す #(ファイルに変更があれば、失われる)
git clean -n で確認して、 git clean -f で追跡対象以外(無視するファイルは除く)を削除できる。 なお、 - カレントディレクトリ以下のディレクトリ内も対象にするときは -d を付ける - gitignoreで無視しているファイルも消すときは - xを付ける - 対話的に消したいときは -iを付ける
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 [リモートリポジトリ/]ブランチ をしてもよい。
git merge [リモートリポジトリ/]ブランチ # 現在のブランチに、指定のブランチをマージする # (コンフリクトした場合は手動で解決する) よくある例) masterブランチを修正して commitした。pushすると、originの masterブランチが変更されて いたため rejectされた。この場合は次のようにする。 $ git fetch $ git merge --no-commit --no-ff origin/master ここでコンフリクトを手動で解消 $ git add 解消したファイル $ git commit -m "merge branch origin/master into master" $ git push
単純なコンフリクトの場合は、ファイルにコンフリクトの内容が、 <<<<<<< HEAD ほげほげ ======= ほげほげ >>>>>>> SHA1 と書き込まれているので、エディタで修正して、保存する。その後、add, commit する。
コンフリクトが出たとき git show :1:ファイル名 > ファイル名.base git show :2:ファイル名 > ファイル名.ours git show :3:ファイル名 > ファイル名.theirs 3つのファイルについて手動で修正し、 git merge-file -p ファイル名.{ours,base,theirs} > ファイル名 #再度マージ? をして、問題無ければ add, commitする。 3方向のdiff(コンフリクトのマーカー含)のファイルを作りたいとき、 git checkout --conflict=diff3 ファイル名 #デフォルトでは--conflict=merge
git checkout --conflict=merge ファイル名
(実例)作業領域に更新があり、コミットしていなく、したくないが、リモートリポジトリの更新を pullしたいとき $ git stash $ git pull $ git stash pop # popする(applyして、リストからは削除) で良いらしい。 --skip-worktreeしたファイルがコンフリクトしていた場合は、コンフリクトのためAbortするので、 --no-skip-worktreeしてから git stashする。 git stash [ save [--include-untracked]or?[--all] ["メッセージ(日付を入れると良い)"] ] git stash list git stash apply --index [ stash@{0} ] #auto mergeなどされるようだ。 git stash drop stash@{0} #削除 git stash pop #変更をpopする(リストからは自動で削除される。コンフリクトがあると削除されない) 今の作業ブランチにapplyやpopがされるようだ。 logをみると stashしたものの SHA1がわかるので、ブランチ名をつけて作業してゆくこともできる。
+------>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
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] # リモートリポジトリの一覧表示
作業ディレクトリやステージは 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による)。
作業ディレクトリやステージは commit,push済であるとする $ git fetch --all --tags $ git checkout --track origin/nwp # リモートリポジトリoriginのブランチnwpを追従するローカルのブランチnwp # を作成し、チェックアウトする。 # git checkout -b nwp origin/nwp でも同じ。
git status [-s] # -sは簡潔表示(非追跡対象のファイルは「?? ファイル名」で表示) git status -sb # -sは簡潔表示、-bは現在のブランチを表示
.gitignore ファイル このファイルを使って無視するファイルを指定できる(非追跡対象をstatusで表示させなくする等)。 再帰的にディレクトリ階層に適用される。 利用できる正規表現は git help gitignore や man gitignore を見よ。 (例)作業ディレクトリに以下の内容で .gitignoreを置く *.x *.o *.a *~
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 タブの次に空白がある
git show オブジェクト[:ファイル] # コミットやその内容(ファイル)を表示する。 # オブジェクトは SHA1や、ブランチ、タグなどで指定 # :ファイル 特定のファイルのみ表示
コミットログを表示する 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 --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
git mylog --all --follow --date=iso --summary -p -- sampleinp/sample_H2mb64g64.out.chked #-pで差分を表示、--followでリネームに対応、--summaryでリネームなどの判断材料も表示 #もし -pを付けないと1行のログだけで表示
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がわかる)
/bin/rm -rf .git a b git init echo foo > a; git add a; git commit -m "add a" git branch other; git checkout other echo bar > b; git add b; git commit -m "add b" git checkout master git merge --no-commit --no-ff other echo bart > a; git add a git commit -m "merge branch other" echo "*** log"; git log -25 --oneline --decorate --graph --all echo "*** log -p"; git log -p echo "*** log --cc"; git log --cc
git show sha1 #コミットを表示(差分も表示される) git log --cc sha1 sha1^..sha1 #親1からのログを表示(--ccなので差分も表示) git log --cc sha1 sha1^1..sha1 #親1からのログを表示 git log --cc sha1 sha1^2..sha1 #親2からのログを表示 なお、sha1^1か sha1^2かのどちらか一方だけが、マージコミットのログのみが表示される。
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 も見よ。
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 でバックアップがとられる。
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 するとローカルリポジトリのリモートブランチは自動的に削除される?)
リモートリポジトリにブランチが無い場合
ローカルリポジトリのローカルブランチを、リモートリポジトリに送ってブランチを作り、追跡するように設定 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を省略するとhogeBの所はカレントブランチが使われる?)
git fetch --all # 登録されている全てのリモートリポジトリから最新情報を取得する git fetch --all --tags # 上記に加え、リモートリポジトリにあるタグも取得する git fetch [リモートリポジトリ] [ブランチ]
git pull [リモートリポジトリ] # fetchし、mergeすることに相当
git push [リモートリポジトリ] [ブランチ] [--tags] # 競合が発生した場合は pushはできない(fetch, mergeし、競合解決してから pushする) # --tagsはタグもプッシュする
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など)のタグ名を削除
git checkout {ブランチ|タグ|sha1など} #指定のものをチェックアウトする #非追跡対象のファイルなどは、そのまま残される。 #sha1でチェックアウトした時、detached HEADになるが、普通どおり修正してコミット #できる(ブランチ名を新たにつける方が取り扱いやすい)。
git checkout -b ブランチ {リモートリポジトリ/ブランチ|タグ|sha1など} #指定したものをチェックアウトし、 #-bで指定したブランチを作成する #リモートリポジトリ/ブランチを指定した場合、 #作成したブランチはリモートブランチ(リモートリポジトリ/ブランチ)を追跡するように設定される。 git checkout --track リモートリポジトリ/ブランチ #git checkout -b ブランチ リモートリポジトリ/ブランチ #と同じ #作成したブランチはリモートブランチ(リモートリポジトリ/ブランチ)を追跡するように設定される。
detachして、追加修正した記録を残したいときの例 $ git commit -m "a commit for debug tests" #とりあえずコミットした $ git branch debug_hoge #ブランチにして、 $ git tag debug_hoge_20230322 #タグを付けて、 $ git push --set-upstream origin debug_hoge #リモートリポジトリにpush $ git push --tags #タグもpush $ git push origin --delete debug_hoge #リモートブランチを削除 $ git checkout master $ git branch -D debug_sotu_ngrid #ローカルブランチを削除 最後の三行は $ git checkout master $ git branch -D -r debug_sotu_ngrid か。
gitk [--all] [ファイル] # git log などのGUIツール
git help コマンド名 #gitのオンラインマニュアル
git diff差分はそのままでパッチファイルになっている。 パッチの当て方 patch [--dry-run] -p1 < パッチファイル #--dry-runは何が行われるかを表示するだけ。
git config [--global] -l # .git/configを表示 git config [--global] -e # .git/configを編集
git config --global color.decorate.tag "blue" #青色にする(see: git help config)
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から #のぶんを表示する
まず、ブラウザで名前を付けてリポジトリを作る。 ここへのpushの仕方が表示されるので、ローカルに作っておいたリポジトリをpushする。
tagを消すとき git push origin :refs/tags/タグ名 branchを消すとき git push origin :refs/heads/ブランチ名
$ 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 をすると表示されなくなる
localな設定 git config --local core.quotepath false #.git/configに保存される git config --local --unset core.quotepath #設定を元に戻す globalな設定 git config --global core.quotepath false #~/.gitconfigに保存される git config --global --unset core.quotepath
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'はタブ。) (補足) $ grep $'\t' makefile と同じことは $ grep -P '\t' makefile #perl互換の正規表現 でできるが、 デフォルトでは grepは \t をタブ文字コードと理解しない(ほとんどのメタ文字利用不可)。 そのため bashで $'\t' によりタブ文字コードを grepに渡している形。 さらに、bashではタブ文字コードを入力することが出来るので(Ctrl-v Tabで入力) タブ文字コードをシングルクォーテーションで括って grepに渡すこともできる。 c.f. $ grep \\t makefile #これは'\t'の検索と同じ $ grep '\t' makefile #ただの tの検索になる $ grep '\\t' makefile #これは \tの2文字の検索 $ grep '\\\t' makefile #これも \tの2文字の検索 $ grep '※ここでCtrl-v Tab' makefile #これは$'\t'の検索と同じ
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
次の 1)または 2)の方法でフックを作り、英語以外の注釈をエラーにすることができる。
1) ベアリポジトリに pushされるとき、
2) ローカルリポジトリで commitするとき。
なお、リポジトリを cloneしたときに、自動的に 2)の方法のフックを設置することはできない。
そのため 2)は各ユーザが自分で手動でフックを設置しなければならない。
一方、1)は push時にエラーになるが、エラーとなったユーザはコミットを作り直さなくてはならない。
(注) 2023/09/30にフックを作ったが、バグが無いとも言い切れない
hooksディレクトリに以下の内容を updateというファイル名で保存する。
#!/bin/sh # 2023/09/30 okazaki,i MYDEBUG=0 #1 or 0 #get the commit range to be push refname="$1" oldrev="$2" newrev="$3" #rearrange the commit range zero="0000000000000000000000000000000000000000" if [ $oldrev != $zero ]; then range="$oldrev..$newrev" else range="$newrev" fi #check charaset, then reject or continue to the commit. [ $MYDEBUG -ne 0 ] && echo "MY update: git rev-list" 2>&1 [ $MYDEBUG -ne 0 ] && git rev-list $range 2>&1 for c in `git rev-list $range`; do [ $MYDEBUG -ne 0 ] && echo "MY update: git cat-file, for $c" git cat-file commit $c | sed '1,/^$/d' > /tmp/hook.$$ chara=`file -i /tmp/hook.$$ | sed 's/^.*charset=\(.*\)/\1/'` rm -f /tmp/hook.$$ [ $MYDEBUG -ne 0 ] && echo "chara=$chara" 2>&1 [ $MYDEBUG -ne 0 ] && echo "using /tmp/hook.$$" 2>&1 #check charaset if [ x$chara != x"us-ascii" ]; then echo "REJECT your message which is not us-ascii." 2>&1 exit 1 fi done [ $MYDEBUG -ne 0 ] && echo "CONTINUE to commit." 2>&1 exit 0
.git/hooksディレクトリに以下の内容を commit-msgというファイル名で保存する。
#!/bin/sh # 2023/09/30 okazaki,i MYDEBUG=0 #1 or 0 #get commit the message msg=`cat "$1"` [ $MYDEBUG -ne 0 ] && echo "MY commit-msg: $msg" #determine charaset echo "$msg" > /tmp/hook.$$ chara=`file -i /tmp/hook.$$ | sed 's/^.*charset=\(.*\)/\1/'` rm -f /tmp/hook.$$ [ $MYDEBUG -ne 0 ] && echo "MY commit-msg: chara=$chara" 2>&1 [ $MYDEBUG -ne 0 ] && echo "using /tmp/hook.$$" 2>&1 #check charaset, then reject or continue to the commit. if [ x$chara != x"us-ascii" ]; then echo "REJECT your message which is not us-ascii." 2>&1 exit 1 fi [ $MYDEBUG -ne 0 ] && echo "CONTINUE to commit." 2>&1 exit 0