「Git」の版間の差分
細 (→Model) |
(添付ファイルの削除) |
||
| 16行目: | 16行目: | ||
GitHubではREADME系ファイルを描画表示してくれる。READMEとREADME.*が対象。index.html系はだめ。 | GitHubではREADME系ファイルを描画表示してくれる。READMEとREADME.*が対象。index.html系はだめ。 | ||
==== PR ==== | ==== PR+issue ==== | ||
Pull Request。第三者の修正を、本体側でgit pull (取り込む) ことのリクエスト・要請。 | Pull Request。第三者の修正を、本体側でgit pull (取り込む) ことのリクエスト・要請。 | ||
| 67行目: | 67行目: | ||
# 元ブランチを復元 | # 元ブランチを復元 | ||
# PR一覧画面を出してチェックしてステータス変更 | # PR一覧画面を出してチェックしてステータス変更 | ||
===== 添付ファイルの削除 ===== | |||
[https://tech.coincheck.blog/entry/2022/10/21/113906 GitHubのIssueやPull requestsにアップロードした画像の削除 - Coincheck Tech Blog] | |||
issue+pull requestに添付したファイルは、外部のアップローダーを使っており、URLは公開されている。 | |||
削除は専用フォームから依頼が必要で面倒。 | |||
アップロードは注意する。 | |||
==== Other ==== | ==== Other ==== | ||
2025年10月16日 (木) 15:54時点における版
Host
GitHub
Account
Username may only contain alphanumeric characters or single hyphens, and cannot begin or end with a hyphen. ユーザー名は、英数字と-のみが使用可能。
組織別にアカウントを分けるなら、かぶらないように末尾に-組織名のようなサフィックスがあるとよいだろう。
README
https://chatgpt.com/c/6779ea86-96e4-800b-ba81-eeca2793d397
GitHubではREADME系ファイルを描画表示してくれる。READMEとREADME.*が対象。index.html系はだめ。
PR+issue
Pull Request。第三者の修正を、本体側でgit pull (取り込む) ことのリクエスト・要請。
PR後のブランチ更新
PR作成後にブランチの内容を更新する場合は注意が必要。
マージ元ブランチはPR作成時のバージョンで固定される。マージ元とマージ先の両方にたとえばdevelopなどの共通の修正を取り込んだ場合、GitHubの画面でマージ元ブランチも選択し直して、参照バージョンを更新しておく。
そうしないと、マージ先だけ反映されてしまって、想定していない差分が大量に表示される。
Web UIでの編集
素人の私でもわかる「Webブラウザだけでgithubのプルリクをする方法」 #GitHub - Qiita
他の人のリポジトリーで修正箇所を見つけたら、そのファイルの編集ボタンで編集して、ボタン操作で自動でフォークしてPRを作れる。
レビュー指摘が来た場合、自分の該当ブランチを開いて、編集したらそのままコミットできる。
1ファイル1コミットの場合、Web UIで完結できる。修正が少ない場合、悪くない。
範囲選択
プルリクエストで提案された変更をレビューする - GitHub Docs
[Pull requests]-[File changed] で変更ファイルについてコメントする形でレビューする。
この際、行部分をドラッグすると、行を指定してブロックでコメントできる。
ファイル自体にコメントするには、右上のコメントマーク。
マージ後修正
GitHubでMerge済みのPull requestにCommitを追加して再度Mergeできるのか確認してみた | DevelopersIO
一度マージされたら、同じブランチに追加コミットしても、再マージはできない。
PRの作成が必要。
マージロック
右上の [Reviewers] のところの [Convert to draft] で下書きにできる。この状態だとマージ不能になる。
一番下の [No conflicts with base branch] あたりの [ready for review] で元に戻せる。
リモートブランチ削除後復元
pull request 中のブランチの削除と復元 - GitHub Docs
マージ済みブランチの整理中に間違えて、削除してしまった。
リモートブランチを削除すると、PRがあったらclosedになる。
復元するには以下の手順を取る。
- 元ブランチを復元
- PR一覧画面を出してチェックしてステータス変更
添付ファイルの削除
GitHubのIssueやPull requestsにアップロードした画像の削除 - Coincheck Tech Blog
issue+pull requestに添付したファイルは、外部のアップローダーを使っており、URLは公開されている。
削除は専用フォームから依頼が必要で面倒。
アップロードは注意する。
Other
remote: Support for password authentication was removed on August 13, 2021.
git pushすると以下のようなエラーが出る。
remote: Support for password authentication was removed on August 13, 2021. remote: Please see https://docs.github.com/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication. fatal: Authentication failed for 'https://github.com/senooken/dotfile/'
2021-08-13からパスワード認証が使用不能になった。
アクセストークンを使う。
「個人用アクセス トークンを管理する - GitHub Docs」に設定方法がある。
必要な権限が明記されていなくてややこしい。
https://chatgpt.com/share/682ac434-8598-800b-aaad-de73b48a337d
[Fine-grained tokens]と[Classic token]とで違う。
- [Settings]-[Developer settings]-[Personal access token]
- Tokens (classic) (https://github.com/settings/tokens)-[Generate new token]
- ☑️ repo
- [Fine-grained tokens] (https://github.com/settings/personal-access-tokens) -[Generate new token]
- Repository access: ◉ All repositories
- Permissions
- Account Repository permissions:
- Contents=Read and write
- Account Repository permissions:
これで生成されたパスワードを入力すればOK。
WSLに認証情報保存
Git Credential Manager (GCM) でGithubへの認証をセキュアに実現する (Windows, WSL2, Linux) – Portablecode.info
Githubにpush/pullしようとすると、通常であれば、認証マネージャーが起動して、そこの認証情報を流用してくれる。ただ、WSLを使っている場合、設定が必要。
Git for Windowsをインストールしていれば、それに同梱されている。パスの設定だけ行う。
git config --global credential.helper "/mnt/c/Program\ Files/Git/mingw64/bin/git-credential-manager.exe"
Server
Gitで自前のサーバー、リモートリポジトリーを設置する方法がある。
いくつか考慮事項がある。どのプロトコルを使うかが重要。
https://grok.com/share/c2hhcmQtMw%3D%3D_2b4fcc61-0d45-4d12-abac-6b29246b3716
基本事項として、あくまでgitサーバーはリポジトリー機能のみの提供。Web表示は別。
閲覧には、gitweb/cigt/tracなどの別ソフトを使う。
リポジトリー機能+閲覧を一緒にやりたければ、gitlab/phorgeとか専用のソフトが必要。だけど、VPSが必要になる。
CGIの範囲で、レンタルサーバーで完結させたければ、git server+tracのような組み合わせがほぼ必須。
プロトコル
Gitサーバーを設置する際、プロトコルに応じて、方法が大きく異なる。
- Local: リモートリポジトリーを全員がアクセス可能なディスク上に配置。file://でアクセス。
- HTTP: HTTPを使う方法。一般的。ただ、v1.6.5までは読取だけだった。v1.6.6からSmart HTTPが登場して、書き込みも可能になった。
- SSH: 匿名アクセス不能。読込専用でも。自分専用。非公開。
- Git: 最高速。ただし、認証の仕組みがない。独自のデーモンが必要で用意が大変。
Smart HTTPほぼ一択。
サーバー用Gitの取得
Gitサーバー用のリポジトリーを用意する。基本は既存のGitリポジトリーだが、サーバー用に作業ファイルのないリポジトリーにする。
既存リポジトリーをエクスポートして作成する。git clone --baseで他のローカルgitリポジトリーから作る。
$ git clone --bare my_project my_project.git
このコマンドはおおざっぱには以下のコマンドと同じ。
$ cp -Rf my_project/.git my_project.git
Smart HTTP
Smart HTTPによる設置方法。基本はGit付属のCGIスクリプトとサーバー、認証設定のみ。
git-http-backendスクリプトを使う。
Model
Apache HTTP Serverでの設置手順の場合。
mod_cgi/mod_alias/mod_env/mod_rewriteを有効にする。
$ sudo apt-get install apache2 apache2-utils $ a2enmod cgi alias env rewrite
gitの管理ルートディレクトリー (例: /opt/git) をwww-dataのグループに変更して、httpdから読書可能にする。
$ chgrp -R www-data /opt/git
/gitパスアクセス時に、git-http-backendを割り当てる。
SetEnv GIT_PROJECT_ROOT /opt/git SetEnv GIT_HTTP_EXPORT_ALL ScriptAlias /git/ /usr/lib/git-core/git-http-backend/
他に、GIT_PROJECT_ROOTでgitの管理ルートディレクトリーを設定。GIT_HTTP_EXPORT_ALLを設定して、書き込み可能にする。これを設定しない場合、クライアントからは読込専用で、git-daemon-export-okファイルが保存されたリポジトリーのみ (git daemonと同じ挙動)。
最後にgit-http-backendへのアクセス許可の設定と、書き込み認証を設定する。
RewriteEngine On
RewriteCond %{QUERY_STRING} service=git-receive-pack [OR]
RewriteCond %{REQUEST_URI} /git-receive-pack$
RewriteRule ^/git/ - [E=AUTHREQUIRED]
<Files "git-http-backend">
AuthType Basic
AuthName "Git Access"
AuthUserFile /opt/git/.htpasswd
Require valid-user
Order deny,allow
Deny from env=AUTHREQUIRED
Satisfy any
</Files>
order/deny/satisfyを使わない場合、以下だと思う。
RewriteEngine On
RewriteCond %{QUERY_STRING} service=git-receive-pack [OR]
RewriteCond %{REQUEST_URI} /git-receive-pack$
RewriteRule ^/git/ - [E=AUTHREQUIRED]
<Files "git-http-backend">
AuthType Basic
AuthName "Git Access"
AuthUserFile /opt/git/.htpasswd
Require valid-user
Require not env AUTHREQUIRED
</Files>
これの意味。git push時 (service=git-receive-pack /git-receive-pack) はパスワード認証が必要だが、それ以外はパスワード不要 (require not envにマッチ) という意味 (https://grok.com/share/c2hhcmQtMw%3D%3D_826f3cbf-b07d-434a-a573-a921b8eee6ea)。
さらに、対象ユーザー全員のパスワードが記述された.htaccessファイルを用意。ユーザーschaconを追加する場合以下を実行する。
$ htpasswd -c /opt/git/.htpasswd schacon
https://grok.com/share/c2hhcmQtMw%3D%3D_059bbb94-5e7b-4f02-99bb-1303b51d62a9
Digest認証もできるが、複雑になるだけで、あまり意味がないのでBasic認証でやるのがよさそう。
git-receive-packがいきなり登場して混乱した。このパスはgit push時に使っている模様。
git pushすると以下を通信して、リモートリポジトリーに書き込む模様。
- GET /push-test.git/info/refs?service=git-receive-pack
- POST /push-test.git/git-receive-pack
なので、これらのパスへのアクセスに認証をかけている模様。
Gitolite
About
- https://grok.com/share/c2hhcmQtMw%3D%3D_461ea368-264f-4d96-b203-fdd120722ec6
- https://grok.com/share/c2hhcmQtMw%3D%3D_270a9b75-83a8-47d9-ade9-d3b1d8a44b41
- Gitolite · git
- Gitolite
git-http-backendを使う場合、apacheのbasic認証を使う。と、アカウント管理が面倒になる。
gitoliteを使うとそのあたりカバーされるらしい。基本はsshだけど、httpでもできるとか。
gitolite-admin.gitという、専用のgitリポジトリーで管理しているとか。
Auth
ただ、gitoliteはもともとSSH前提。HTTPもいけるがその場合apacheのbasic認証との併用で、basic認証のユーザーとsshのユーザーが対応している。
その都合、basic認証とssh認証の二重管理が必要。アカウント管理を楽にしたかったのに、二重管理になってしまい本末転倒。やっぱり、git-http-backend+apacheで構築するのがベスト。
アカウント管理が必要なら、自分で管理用のツール・スクリプトを作ったほうがよさそう。
https://grok.com/share/c2hhcmQtMw%3D%3D_e86d9e67-edfa-4a60-88f4-6537a0b06742
あるいは、自作するほかに、oauthやldapの外部認証を使う方法がある。外部認証でいけるなら、これが確実かも。ただ、この外部認証を自分でホストする必要があって、今の段階だとこれを考えるのが面倒くさい。当面は手動管理でいく。
Install
View
log
- 逆順表示: --reverse
- 差分表示: -p
Other
親コミットの参照
Gitは自分より後ろ (新しい) コミットは参照しやすいが、その逆の先祖の履歴は参照しにくい。なくはない。
^Nと~Nで対象コミットのN番目の親コミットを参照できる。これで一応辿れる。
gitrevisions
Git - gitrevisions Documentation
Gitでは多くの方法でコミット (<rev>) を参照できる。
| 種類 | 例 | 説明 |
|---|---|---|
| <sha1> | dae86e1950b1277e545cee180551750029cfe735 dae86e | SHA!-1オブジェクト (40バイトの16進数)、またはリポジトリー内で一意の先頭部分文字列。 |
| <describeOutput> | v1.7.4.2-679-g3bee7fb | git describeの出力。タグ名など |
| <refname> | master、heads/master、refs/heads/master | シンボリック参照名。 |
refname
refnameはいろいろある。
diff
差分無視
git diffの--ignoreオプションにおけるスペース、タブ、改行の扱いを理解する #Git - Qiita
-wでインデント違いを無視してくれる。
差分ファイル抽出
情報源: gitで差分ファイルを抽出する #Git - Qiita。
git archiveとgit diffを組み合わせる。 git archive --format=zip --prefix=root/ HEAD `git diff --diff-filter=d --name-only HEAD^ HEAD` -o archive.zip ただし、この方法はファイル数がARG_MAX以下の場合だけ。ファイル数が多い場合だめ。
git diff --name-onlyで一覧を出力させて、1個ずつcp -pで階層を維持してコピーするしかないかも?
例:
mkdir -p archive
git diff --name-only new_base 44765_upgrade-base-version | xargs -i cp -p --parent "{}" archive/
オプション
差分ファイル一覧を出力するオプションがいくつかある。
- -z: 異常な文字があったときの扱い用。ファイルの区切りをNULにする。
- --name-only: ファイル名一覧。
- --name-status: ファイル名一覧+ステータス。
- --diff-filter=ACDMRTUXB: 差分表示のファイルを絞り込む。A=Added, C=Copied, D=Deleted=, M=Modified, R=Renamed, T=Type changed, U=Unmerged, X=Unkonwn, B=Broken, *=All。小文字にすると、除外 (ブラックリスト) になる。--diff-filter=ACMを覚えておくと、チェックで便利そう。
- --cached/--staged: git addした後のステージングのファイルと最新コミットを比較する。このオプションをつけない場合、git addしていない作業ファイルと最新コミットの比較になって、ステージングは除外される。--stagedは--cachedの別名だが、こちらのほうが覚えやすい。
Commit
コミットオプション
Git - git-commit Documentation
コミットメッセージ指定のためのオプションがある。
- -m|--message <message>: コミットを文字列で指定。複数指定可能で、その場合段落で区切ってくれる。2行目以後を書きたい場合などで使う。
- -C|--reuse-message <commit>: 指定したコミットのコミット情報を再使用する。
- -c|--reedit-message <commit>: -Cの同じだが、編集画面を表示してコミットメッセージを編集して再使用する。
- -F|--file=<file>: 指定したファイルをコミットメッセージに使う。-を指定すると標準入力を使う。
基本は-m。-mの複数指定。
過去コミットのメールアドレスの変更
- How can I change the author (name / email) of a commit? | Learn Version Control with Git
- Gitのcommitの名前やメールアドレスを過去からまとめて変更する
単一コミットのメールアドレスを指定する場合、commitに--authorを指定する。 git commit --author="John Doe <john@doe.org>" --amendと併用することで、過去コミットも変更できる。
数が少ないなら、rebase -iで1個ずつamendする。数が多いならfilter-branch。
第一コミットの変更
- [Git 最初のコミットを含めてrebase -iする方法 | DevelopersIO]
- Git - git-rebase Documentation
通常、第一コミットはammend以外では変更できない。
rebase --root [branch] でブランチの第一コミットも参照して改変可能。
ファイルを間違えて追加してしまった場合は、git rm -r --cached で削除してコミットし直せばいい。
コミットログの文字化け
Git コミットログの文字化けではまる - wadahiroの日記
git commitやgit commi --amend実行時のコミットログがgit logで文字化けすることがある。
これは、git commit時に実行しているテキストエディター (vim) の文字エンコーディング設定が由来の可能性が高い。
gitはデフォルトでutf-8なので、以下のような内容を~/.vimrcに書いておいて、utf-8にしておけば解消する。
"" Encoding
set encoding=utf-8
set fileencodings=ucs-bom,iso-2022-jp,utf-8,euc-jp,cp932,cp1252
set fileformats=unix,dos,mac
augroup main
autocmd!
augroup END
"" Fix 'fileencoding' to use 'encoding' if the buffer only ASCII characters.
autocmd main BufReadPost *
\ if &modifiable && !search('[^\x00-\x7F]', 'cnw')
\ | setlocal fileencoding=utf-8
\ | endif
コミット同士の比較
コマンドで綺麗にはできない。git diffはブランチ同士の比較でコミット以外の過去の状態も比較する。
コミット同士で比較するなら、git showの出力結果をファイルに出力してdiff -uで比較するしかない。
git show sha1 >old.diff git show sha1 >new.diff diff -u old.diff new.diff
別のディレクトリーへの修正適用
https://chatgpt.com/c/67bea3ff-56c4-800b-ae92-d40299ad5ade
あるディレクトリーに適用した修正を、ルートのディレクトリー名だけが異なる別ファイルに適用したいことがある。
修正内容の差分をgit format-patch/git diff/git showでファイルに出力して、ファイル内のパスを変更して、そのファイルを使ってgit applyするとうまく取り込める。
add
gitでファイルを管理下のステージングに追加する方法がいくつかある。
- git add -A: リポジトリーツリーの、新規、削除、修正を全て取り込む。
- git add .: 現在ディレクトリー以下。削除は無視される。
git add -Aとgit add .はほぼ同じ。Git 2.0以降ではgit add -Aがデフォルトになっているらしい (https://chatgpt.com/c/67f4e2c7-a240-800b-8084-9650ef61a47e)。
ammendの打消し
間違えて実行したgit commit --amendを元に戻す方法 #Git - Qiita
git commit -amendを取り消すorキャンセルする方法 - まさかろぐ
コミット中に間違いに気づいた場合、コミットメッセージの入力中に、メッセージを空にすると中断できる。
git reset --soft HEAD@{1}
これで直前のコミットの状態に戻せる。あるいは、git reflogで修正前のコミットを探すとか。
branch
Git - git-branch Documentation
先頭アスタリスクの除去
git branch - List all local git branches without an asterisk - Stack Overflow
git branchを実行すると現在ブランチの先頭に*のアスタリスクのマークがつく。これが邪魔。git branch -rだとつかない。除去したい。
あまりいい方法はない。
git for-each-ref --format='%(refname:short)' refs/heads/ git branch --format='%(refname:short)' git branch | cut -c 3-
2番目の方法が綺麗。
誤ったブランチへのコミットの付け直し
- [初心者向け Gitで間違ったブランチにしたコミットを別ブランチに付け替える | DevelopersIO]
- [Git誤ったブランチで実施した変更を正しいブランチに移動する | DevelopersIO]
ブランチを変えずに作業していて、コミット量が増えたので、別ブランチにしておけばよかったということがあったりする。
いくつか方法がある。
- cherry-pickで変更コミットだけ別ブランチに抽出。
- git checkoutとreset --hardで分離: 現在の状態を一旦別ブランチにしてコピー。その後、元ブランチはgit reset --hardで打ち消す。
- git rebase --onto <別ブランチ> 起点コミット でコミットを付け替えて、ブランチを削除、改名して元のブランチの名前にする。付け替え場、起点コミットで元のベースブランチにする。
git rebase --ontoがきれい。
他のブランチとの同一化
git diff HEAD master | patch -p 1
patchの他にgit applyでもいい。
remote
リモートトラッキングブランチという概念。
gitのpush/pull時の対象リモートリポジトリーのブランチのローカルの対応ブランチ。リモートブランチのデータのローカルの管理用。
- git branch -u|--set-upstream-to <upstream>: リモートトラッキングブランチを指定。
- git branch --unset-upstream: 設定済みのリモートトラッキングブランチの対応を解除。
マージ済みブランチの一括削除
放置すると、マージ済みブランチが残る。うざい。
2個目の記事が特に良かった。
基本的な考え方がいくつかある。
## ローカルブランチの削除 git branch -d <branch> ## リモートブランチの削除 git push -d origin <branch> ## 削除済みリモートブランチの、リモートトラッキングブランチの削除 git fetch -p ## マージ済みローカルブランチの一覧 git branch --merged[=origin/develop] ## マージ済み全ブランチの一覧 git branch --merged[=origin/develop] -r
ローカルブランチの場合、git branch --mergedの一覧に対して、git branch -d を実行していくイメージ。ついでに、git push -dもしてもいいかも。
ただし、main/master/developなど削除から除外したいブランチはあるだろう。
git branch --mergedには引数を指定可能で、マージ先のブランチを指定できる。これを指定しないと、途中の集約用ブランチへのマージもマージ済みと認識されるので、必須だろう。
git branch -rでリモートブランチもリストに含められる。
これらを組み合わせてシェルスクリプトを作る。
## ローカルブランチのローカル・リモートの一括削除
git branch --format='%(refname:short)' --merged origin/develop |
grep -v -e '^master' -e '^main' -e '^develop' |
xargs -I {} sh -c 'git branch -d {} && git push -d origin {}'
## リモートブランチの一括削除
git branch --format='%(refname:short)' --merged origin/develop -r |
grep -v -e '^origin/master' -e '^origin/main' -e '^origin/develop' |
sed 's@^origin/@@' |
xargs -I {} sh -c 'git branch -d {} ; git push -d origin {}'
Merge
rebase時のマージコミット維持
git rebase -iはマージコミットを削除してしまう。マージコミットを残したいなら、-rを指定する。昔は-pだった。
-rを忘れてしまった場合、git reflogでリベース前のコミットを探してgit reset --hardでそのコミットに戻してからやり直す。
マージコミット後のコミット追加
マージコミット後に次の開発作業を始めることが多い。が、直後の初回のコミットを追加したい場合困る。
git rebase -iにすると、コミットが残るから。編集はできるが、その直前にコミットの追加ができない。マージコミットは扱いが特殊で直接rebaseで編集できない。
しかたないので、該当コミットでブランチを作成して、コミット。その後、既存の修正ブランチをrebaseでそのコミットの後にくっつける。これでいける。
マージコミットの打ち消し
マージコミットは扱いがやや特殊。
git revert -m 1 マージコミット git reset --hard HEAD~1 # マージコミット前
どちらか。
https://chatgpt.com/c/679983bc-a96c-800b-9d8c-a15873d1d068
git revert -mは1か2の数字を指定する。これは、マージはマージ元とマージ先の親ブランチが2個あり、どちらを基準にリバートするかを指定するためにある。
基本はマージ元 (mainやdevelopブランチ) の1を指定する。マージ先のfeatureブランチは2だがこちらを指定することはあまないだろう。
git checkoutなしのmerge
- https://chatgpt.com/c/677f6038-4fa8-800b-9efb-fae4d2a4ab91
- checkoutせずにmergeする #Git - Qiita
- Merge, update, and pull Git branches without using checkouts - Stack Overflow
- Merging Branches Without Checkout (Example)
gitでブランチをマージする場合、基本はマージの取り込み元ブランチに移動してから、対象ブランチを取り込む必要がある。
これは、3wayマージなどのために、マージの元ファイルが必要だからとのこと。
ただ、毎回切り替えるのが面倒くさい。ブランチ同士でのマージが一応可能。
git fetch . src:dst
ただし、このコマンドはfast-fowardsマージの場合だけ。rebase相当。それ以外は上書きされるので、手動マージが必要。注意が必要。
スクリプトの自動処理などで使う感じ。
cherry-pick後のmergeで重複コミット
github - Git でCherry-pick 後に Mergeすると同じCommitの履歴が複数できてしまう - スタック・オーバーフロー
ブランチが2個あって、ブランチでコミット・pushした後、間違えたブランチだと気づいて、別ブランチでcherry-pick。その後、ブランチの内容を取り込むためにまたmergeしたら、cherry-pickのコミットのマージができる。
コミット履歴が残っているから、それを素直に取り込んだだけで、残るのは仕方ない。rebaseやreset --hardで消すしかないが、pushしているから、一人とかじゃないとだめ。
重複コミットは諦めるしかない。
マージコミット前後の比較
MC=cf128108e43b0d614528d2ab04fc9fa4188761e1
git diff ${MC}~ $MC
~でマージコミットの1個前のコミットを参照して差分をとればいい。
git merge --no-ff
https://chatgpt.com/c/67ec9d0c-5cd0-800b-80f3-7905e157fa9f
git mergeすると、デフォルトでfast forwardになる。マージコミットがなくて、履歴は綺麗になる。が、どのブランチがどのタイミングでマージされたかが、履歴でわかりにくい。
基本は機能ブランチ (feature branch) のマージでは、--no-ffを使う。こうすることで、いつマージされたかが明確になる。
Customize
Git config
.netrc
https://social.senooken.jp/conversation/1573147#notice-2217499
Gitのパスワード入力の省略方法に~/.netrcがある。
しかし、man netrcするとわかるけど、これはもともとFTPのためのもの。なぜGitで使えるんだ?Gitの文書で言及がない。
In conversation Thursday, 21-Feb-2019 10:58:47 JST from web permalink
せのお (妹尾 賢)せのお (妹尾 賢) in reply to
理由が分かった。
1. Gitはhttpとhttpsの通信にcURLを使っている。
https://github.com/git/git/blob/master/INSTALL#L141
2. cURLが.netrcにも対応しているから。
https://ec.haxx.se/usingcurl-netrc.html
core.autocrlf
warning: in the working copy of 'docker/README.md', LF will be replaced by CRLF the next time Git touches it
Windowsでは改行にCR+LFを使うが、mac/LinuxはLFのみ。これの違いの処理のための設定がcore.autoclrlf
- true=コミット時にCRLFをLFに自動変換。チェックアウト時に逆。Windows向けの設定。
- false=変換しない。
- input=コミット時にCRLFをLFに自動変換のみ。mac/Linux向け。Windowsではチェックアウト時にCRLFになるが、mac/LinuxはLFになる。
わかりにくい。基本はfalseで良いと思われる。
gitkの文字化け対策
gitkのエンコーディングを設定する - Pistolfly
gitkはシステムのデフォルトエンコーディングで表示しようとするので、文字エンコーディングを指定しておく。
git config --global gui.encoding utf-8
WSLなどで、日本語が表示されない場合、フォントが入っていない可能性が高い。
以下のコマンドで日本語対応フォントをインストールする。
sudo apt install -y fonts-noto-cjk fonts-noto-cjk-extra fonts-ipafont
ファイル名などの文字化け対策
Git for Windows で日本語を使いたい #Vim - Qiita
git config --global gui.encoding utf-8 git config --global core.quotepath false
core.editor
git commitなどで使用するデフォルトのエディター設定。
以下の優先順位になっている。
- core.editor
- VISUAL環境変数
- EDITOR環境変数
- システムデフォルト
core.editorを指定するのがいい。
git config --global core.editor vi
gitignore
gitの管理対象外のファイル。ログや一時ファイルなど。
これで指定していないと、git addすると管理対象に入るし、untracked fileで表示が出る。git add .やディレクトリー指定で一括で管理したい場合に混ざっていると邪魔。
File
- .gitignore: ディレクトリー内。
- $GIT_DIR/info/exclude: リポジトリー固有のローカル。
- core.excludesFile: ~/.gitconfig内で指定するgitignoreファイル。通常、$XDG_CONFIG_HOME/git/ignoreか$HOME/.config/git/ignore。
Format
記述方法を整理する。
- 空行は無視。
- #始まりの行はコメント扱い。
- 終端スペースは無視。
- !接頭辞はパターン否定。つまり、除外ではなく含める。以前除外された一致を再び含める。ただし、親ディレクトリーが除外されている場合、以下のファイルは含められない。パフォーマンス上の理由。順番に注意する。
- /はディレクトリー区切りとして使用。先頭、中間、末尾で登場する。
- 先頭と中間の/は相対パスを意味する。
- それ以外、末尾の/と/なしの場合、現在以下のディレクトリーにもマッチする。
- 末尾が/で終わる場合、ディレクトリーのみに一致。/がない場合、ディレクトリーとファイルの両方に一致。
- *は/以外にマッチ。?は/以外の任意の1文字にマッチ。[a-zA-Z] の範囲記法も使用可能。fnmatch(3) FNM_PATHNAMEフラグのパス名展開に準じる。
- **は特殊な意味がある。
- **/=全ディレクトリー。**/fooは配下の全fooにマッチ。**/foo/barはfoo以下の全barにマッチ。
- /**=配下のすべてにマッチ。
- a/**/b=a/b a/x/b a/x/y/bのすべてにマッチ。
後は特に明記がないが、上から順番に評価されて、最後のマッチが優先されるので、記述の順番に注意する。
反転の!と/の扱いに特に注意が必要。
先頭スラッシュをつけないと、再帰的になる。
$ cat .gitignore
- ディレクトリ foo/bar 以外のすべてを除外
- /*
- !/foo
- /foo/*
- !/foo/bar
空ディレクトリーの維持
How do I add an empty directory to a Git repository? - Stack Overflow
gitは空ディレクトリーを履歴管理できない。何かファイルが必要。
logなど維持したい空ディレクトリーに、以下の内容の.gitignoreを置く。
* !.gitignore
.gitignore以外を無視する。これで.gitignoreのみがあるので管理できる。
指定ファイルのみ除外
!.gitignore ディレクトリーを残す以外 (.gitignore1ファイル以外) に、サンプルファイルなど複数ファイルを残したい場合は、上記のように*で最初に全部除外して指定ファイルのみ含める。/は必要に応じてつける。
gitattributes
Git - gitattributes Documentation
gitignoreに似ていて、パターンにマッチしたパスに対する設定を行える。
- text
- eol
- working-tree-encoding
- ident
- filter
- diff
- merge
- conflict-marker-size
- whitespace
- export-ignore: git archiveなどに含めないことをマーク。
- export-subst
- delta
- encoding
Git hook
特定アクションでカスタムスクリプトを実行する仕組み (hook) がある。クライアントとサーバーとで2のグループになる。クライアントサイドはコミット、マージなどの操作時、サーバーサイドはプッシュコミットの受け取り、ネットワーク操作時に実行される。テスト、リント、デプロイなどいろんな目的に使える。
フックをインストールする
フックはgitのhooksディレクトリー (.git/hooks) に格納されている。git initで同梱スクリプトのサンプル類がここに格納される。.git/hooksに実行可能なファイルを適切な名前 (pre-commit などの拡張子なしのフック名) で配置すれば、以降呼び出される。
クライアントサイドフック
クライアントサイドフックは、リポジトリーのクローン時にはコピーされない。フックを強制したい場合、クライアントサイドではなく、サーバーサイドで行う方がいい。
クライアントサイドフックは多くの種類がある。が、典型的なパターンが3種類ある。
- コミットワークフローフック
- Eメールワークフロースクリプト
- その他
コミットワークフローフック
- pre-commit: コミットメッセージの入力前に実行。コミット前の検査・確認目的で使用する。0以外の値を返すとコミットを中断する。ただし、git commit --no-verifyでスキップできる。静的解析にうってつけのフック。
hookの管理
https://chatgpt.com/c/67fe029c-9ce0-800b-9397-8e1d7f18b303
なお、git hooks自体はgitで管理されていない。プロジェクト内にhooksディレクトリーを配置して、内容を管理して、シンボリックリンクで配置したらいい。README.mdに配置方法を記載したらいい。専用コマンドでもいいけど、どうせ1行だし。
# hooks/pre-commit ln -fs ../../hooks/pre-commit .git/hooks/pre-commit
差分ファイル一覧
hookではコミット対象ファイルなどが変数に入ったりはしない。自分でgitコマンドの結果などで一覧などを取得して処理する。
## 削除以外の追加・修正ファイル git diff --staged --name-only --diff-filter=ACM
Other
submodule
https://git-scm.com/docs/git-submodule
foreach
サブモジュールの全部を一括処理する。 foreach [--recursive] <command> <command>部分では$sm_pathでパスを参照できる。 git submodule foreach 'echo $sm_path `git rev-parse HEAD`'
Entering 'XXX' XXX hash submoduleの中に入ってから実行することに注意する。
便利なコマンド。 git submodule foreach 'git reset --hard'
gitk
problem
ブランチ名が長いと、右クリックしにくい
clean
git未管理のファイルを削除するためのコマンド。間違えると復元不能なので注意する。
必ず-nで削除対象を確認してから、-nの本実行を試すこと。
-x/-Xでgitignoreによる無視ファイルも削除できる。
Mac
- /Library/Developer/CommandLineTools/usr/bin/git
- /Library/Developer/CommandLineTools/usr/libexec/git-core/
上記2箇所がMac標準のgit関係の格納場所。
特に重要な補完ツールは以下にある。
- /Library/Developer/CommandLineTools//usr/share/git-core/
- git-completion.tcsh
- git-completion.zsh
- git-completion.bash
- git-prompt.sh
復元
Git Stashの復元: 誤って削除されたスタッシュの復元方法 #Git-Stash - Qiita
git stash drop実行時に、削除したコミットのSHA1が表示される。
そのSHA1をapplyで指定すれば、取り込める。 git stash apply [stash_hash]
改名と修正
改名と修正を同時にすると、改名を検知できない。
-Mオプションを指定すると、類似度で同時も検知できる。が、基本はリネーム・改名と修正は別コミットにしたほうがよさそう。
squash
squashすると、squash対象コミットが、対象の直前のコミットに含められる。
ファイルのインデックスのみ削除
git rmは単独だと、gitの履歴とローカルファイルからも削除する。追跡対象から削除のみで、ローカルファイルとして残したい場合、--cachedを指定する。
git rm --cached
Remote
リモート
gitの不要なブランチを消すコマンド #Git - Qiita git fetch -p/--prune リモートの削除済みブランチをローカルに同期する。
リモートの最新タグ
https:/stackoverflow.com/questions/20734181/how-to-get-list-of-latest-tags-in-remote-git
git ls-remote --tag --sort=taggerdate
date関係のsortはオブジェクトへのアクセスが必要なので、ローカルにないとダメとか。
https:/git-scm.com/docs/git-ls-remote.html
https:/stackoverflow.com/questions/10649814/get-last-git-tag-from-a-remote-repo-without-cloning
git rev-listでいけそう。
https:/gist.github.com/rponte/fdc0724dd984088606b0
push時リモートブランチ作成
$ git push
fatal: The current branch branch has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin branch
To have this happen automatically for branches without a tracking
upstream, see 'push.autoSetupRemote' in 'git help config'.
$ git config --global push.autoSetupRemote true
デフォルトだとgit push -t origin branchなどのように、リモートブランチを明示する必要がある。が、リモートとローカルのブランチ名は同じことがほとんど。
push.autoSetupRemoteの設定があると、ローカルのブランチ名でリモートブランチも作ってくれる模様。昔はこういうオプションなかった気がする。
