「Git」の版間の差分

提供:senooken JP Wiki
(proxy)
(PR後のブランチ名変更)
 
25行目: 25行目:


そうしないと、マージ先だけ反映されてしまって、想定していない差分が大量に表示される。
そうしないと、マージ先だけ反映されてしまって、想定していない差分が大量に表示される。
===== PR後のブランチ名変更 =====
できない。ブランチ名を変更すると、別のPRにするしかない。
[https://web.archive.org/web/20250919111740/https://stackoverflow.com/questions/20007578/renaming-a-branch-while-on-pull-request git - Renaming a branch while on pull request - Stack Overflow]


===== Web UIでの編集 =====
===== Web UIでの編集 =====

2025年10月30日 (木) 15:47時点における最新版

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

READMEについて - GitHub Docs

GitHubではREADME系ファイルを描画表示してくれる。READMEとREADME.*が対象。index.html系はだめ。

PR+issue

Pull Request。第三者の修正を、本体側でgit pull (取り込む) ことのリクエスト・要請。

PR後のブランチ更新

PR作成後にブランチの内容を更新する場合は注意が必要。

マージ元ブランチはPR作成時のバージョンで固定される。マージ元とマージ先の両方にたとえばdevelopなどの共通の修正を取り込んだ場合、GitHubの画面でマージ元ブランチも選択し直して、参照バージョンを更新しておく。

そうしないと、マージ先だけ反映されてしまって、想定していない差分が大量に表示される。

PR後のブランチ名変更

できない。ブランチ名を変更すると、別のPRにするしかない。

git - Renaming a branch while on pull request - Stack Overflow

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になる。

復元するには以下の手順を取る。

  1. 元ブランチを復元
  2. 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

アクセストークンを使う。

個人用アクセス トークンを管理する - GitHub Docs」に設定方法がある。

必要な権限が明記されていなくてややこしい。

https://chatgpt.com/share/682ac434-8598-800b-aaad-de73b48a337d

[Fine-grained tokens]と[Classic token]とで違う。

  1. [Settings]-[Developer settings]-[Personal access token]
  2. Tokens (classic) (https://github.com/settings/tokens)-[Generate new token]
    1. ☑️ repo
  3. [Fine-grained tokens] (https://github.com/settings/personal-access-tokens) -[Generate new token]
    1. Repository access: ◉ All repositories
    2. Permissions
      1. Account Repository permissions:
        1. Contents=Read and write

これで生成されたパスワードを入力すればOK。

WSLに認証情報保存

WSL2でGit認証を毎回聞かれないようにする

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 - プロトコル

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 - プロトコル

Gitサーバーを設置する際、プロトコルに応じて、方法が大きく異なる。

  • Local: リモートリポジトリーを全員がアクセス可能なディスク上に配置。file://でアクセス。
  • HTTP: HTTPを使う方法。一般的。ただ、v1.6.5までは読取だけだった。v1.6.6からSmart HTTPが登場して、書き込みも可能になった。
  • SSH: 匿名アクセス不能。読込専用でも。自分専用。非公開。
  • Git: 最高速。ただし、認証の仕組みがない。独自のデーモンが必要で用意が大変。

Smart HTTPほぼ一択。

サーバー用Gitの取得

Git - サーバー用の 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

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すると以下を通信して、リモートリポジトリーに書き込む模様。

  1. GET /push-test.git/info/refs?service=git-receive-pack
  2. POST /push-test.git/git-receive-pack

なので、これらのパスへのアクセスに認証をかけている模様。

Gitolite

About

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 - リビジョンの選択

Gitは自分より後ろ (新しい) コミットは参照しやすいが、その逆の先祖の履歴は参照しにくい。なくはない。

^Nと~Nで対象コミットのN番目の親コミットを参照できる。これで一応辿れる。

gitrevisions

Git - gitrevisions Documentation

Git - Revision Selection

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 - git-diff Documentation

差分無視

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の複数指定。

過去コミットのメールアドレスの変更

単一コミットのメールアドレスを指定する場合、commitに--authorを指定する。 git commit --author="John Doe <john@doe.org>" --amendと併用することで、過去コミットも変更できる。

数が少ないなら、rebase -iで1個ずつamendする。数が多いならfilter-branch。

第一コミットの変更

通常、第一コミットは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]

ブランチを変えずに作業していて、コミット量が増えたので、別ブランチにしておけばよかったということがあったりする。

いくつか方法がある。

  1. cherry-pickで変更コミットだけ別ブランチに抽出。
  2. git checkoutとreset --hardで分離: 現在の状態を一旦別ブランチにしてコピー。その後、元ブランチはgit reset --hardで打ち消す。
  3. 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

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

Git - Git の設定

.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

proxy

PROXY=http://example.com:8080
git config --global http.proxy $PROXY
git config --global https.proxy $PROXY
git config --global url."https://".insteadOf git://

gitignore

Git - gitignore Documentation

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

  1. ディレクトリ foo/bar 以外のすべてを除外
    1. /*
    2. !/foo
    3. /foo/*
    4. !/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

Git - Git フック

特定アクションでカスタムスクリプトを実行する仕組み (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

https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E3%81%95%E3%81%BE%E3%81%96%E3%81%BE%E3%81%AA%E3%83%84%E3%83%BC%E3%83%AB-%E3%82%B5%E3%83%96%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB

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の設定があると、ローカルのブランチ名でリモートブランチも作ってくれる模様。昔はこういうオプションなかった気がする。