「Git」の版間の差分

提供:senooken JP Wiki
(PR後のブランチ名変更)
 
(同じ利用者による、間の22版が非表示)
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 (取り込む) ことのリクエスト・要請。


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での編集 =====
67行目: 72行目:
# 元ブランチを復元
# 元ブランチを復元
# PR一覧画面を出してチェックしてステータス変更
# PR一覧画面を出してチェックしてステータス変更
===== 添付ファイルの削除 =====
[https://tech.coincheck.blog/entry/2022/10/21/113906 GitHubのIssueやPull requestsにアップロードした画像の削除 - Coincheck Tech Blog]
issue+pull requestに添付したファイルは、外部のアップローダーを使っており、URLは公開されている。
削除は専用フォームから依頼が必要で面倒。
アップロードは注意する。


==== Other ====
==== Other ====
99行目: 113行目:


これで生成されたパスワードを入力すればOK。
これで生成されたパスワードを入力すればOK。
===== WSLに認証情報保存 =====
[https://web.archive.org/web/20250618024058/https://zenn.dev/toccasystems/articles/wsl2-git-credential-manager WSL2でGit認証を毎回聞かれないようにする]
[https://portablecode.info/2023/05/06/git-credential-manager-windows-wsl2-linux/ 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 ==
[https://git-scm.com/book/ja/v2/Git%e3%82%b5%e3%83%bc%e3%83%90%e3%83%bc-%e3%83%97%e3%83%ad%e3%83%88%e3%82%b3%e3%83%ab 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のような組み合わせがほぼ必須。
=== プロトコル ===
[https://git-scm.com/book/ja/v2/Git%e3%82%b5%e3%83%bc%e3%83%90%e3%83%bc-%e3%83%97%e3%83%ad%e3%83%88%e3%82%b3%e3%83%ab Git - プロトコル]
Gitサーバーを設置する際、プロトコルに応じて、方法が大きく異なる。
* Local: リモートリポジトリーを全員がアクセス可能なディスク上に配置。file://でアクセス。
* HTTP: HTTPを使う方法。一般的。ただ、v1.6.5までは読取だけだった。v1.6.6からSmart HTTPが登場して、書き込みも可能になった。
* SSH: 匿名アクセス不能。読込専用でも。自分専用。非公開。
* Git: 最高速。ただし、認証の仕組みがない。独自のデーモンが必要で用意が大変。
Smart HTTPほぼ一択。
==== サーバー用Gitの取得 ====
[https://git-scm.com/book/ja/v2/Git%e3%82%b5%e3%83%bc%e3%83%90%e3%83%bc-%e3%82%b5%e3%83%bc%e3%83%90%e3%83%bc%e7%94%a8%e3%81%ae-Git-%e3%81%ae%e5%8f%96%e5%be%97 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 ====
[https://git-scm.com/book/ja/v2/Git%e3%82%b5%e3%83%bc%e3%83%90%e3%83%bc-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<nowiki/>)。
さらに、対象ユーザー全員のパスワードが記述された.htaccessファイルを用意。ユーザーschaconを追加する場合以下を実行する。
$ htpasswd -c /opt/git/.htpasswd schacon
https://grok.com/share/c2hhcmQtMw%3D%3D_059bbb94-5e7b-4f02-99bb-1303b51d62a9
Digest認証もできるが、複雑になるだけで、あまり意味がないのでBasic認証でやるのがよさそう。
* [https://git-scm.com/book/ja/v2/Git%E3%81%AE%E5%86%85%E5%81%B4-%E8%BB%A2%E9%80%81%E3%83%97%E3%83%AD%E3%83%88%E3%82%B3%E3%83%AB Git - 転送プロトコル]
* [https://zenn.dev/hirokihello/articles/d5866bc64f13e3f3b8c7 git pushの裏側で何が起こっているのか。~javascriptでgitをリバースエンジニアリングで実装する(4)~]
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
* [https://yunwuxin1.gitbooks.io/git/content/ja/a1ed4f4c6948f27fef097ffaf08a545b/b60cff70126a55243f738debc93cae75.html Gitolite · git]
* [https://gitolite.com/gitolite/ 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 ====
* [https://gitolite.com/gitolite/quick_install.html (unix/ssh experts) quick install and setup - Gitolite]
* [https://gitolite.com/gitolite/http.html HTTP mode install - Gitolite]


== View ==
== View ==
254行目: 416行目:


git add -Aとgit add .はほぼ同じ。Git 2.0以降ではgit add -Aがデフォルトになっているらしい (https://chatgpt.com/c/67f4e2c7-a240-800b-8084-9650ef61a47e<nowiki/>)。
git add -Aとgit add .はほぼ同じ。Git 2.0以降ではgit add -Aがデフォルトになっているらしい (https://chatgpt.com/c/67f4e2c7-a240-800b-8084-9650ef61a47e<nowiki/>)。
=== ammendの打消し ===
[https://qiita.com/s_horikoshi/items/21f6bc12dfb98ebdfcb9 間違えて実行したgit commit --amendを元に戻す方法 #Git - Qiita]
[https://mz-kb.com/blog/2018/07/12/git-commit-amend-how-to-cancel/ git commit -amendを取り消すorキャンセルする方法 - まさかろぐ]
コミット中に間違いに気づいた場合、コミットメッセージの入力中に、メッセージを空にすると中断できる。
git reset --soft HEAD@{1}
これで直前のコミットの状態に戻せる。あるいは、git reflogで修正前のコミットを探すとか。


== branch ==
== branch ==
279行目: 450行目:
# cherry-pickで変更コミットだけ別ブランチに抽出。
# cherry-pickで変更コミットだけ別ブランチに抽出。
# git checkoutとreset --hardで分離: 現在の状態を一旦別ブランチにしてコピー。その後、元ブランチはgit reset --hardで打ち消す。
# git checkoutとreset --hardで分離: 現在の状態を一旦別ブランチにしてコピー。その後、元ブランチはgit reset --hardで打ち消す。
# git rebase --onto <別ブランチ> 起点コミット でコミットを付け替えて、ブランチを削除、解明して元のブランチの名前にする。
# git rebase --onto <別ブランチ> 起点コミット でコミットを付け替えて、ブランチを削除、改名して元のブランチの名前にする。付け替え場、起点コミットで元のベースブランチにする。


git rebase --ontoがきれい。
git rebase --ontoがきれい。
401行目: 572行目:
基本は機能ブランチ (feature branch) のマージでは、--no-ffを使う。こうすることで、いつマージされたかが明確になる。
基本は機能ブランチ (feature branch) のマージでは、--no-ffを使う。こうすることで、いつマージされたかが明確になる。


== stash ==
== Customize ==


=== 復元 ===
=== Git config ===
[https://qiita.com/generosity-naman/items/237338f8fe5b7e3b9a76 Git Stashの復元: 誤って削除されたスタッシュの復元方法 #Git-Stash - Qiita]
[https://git-scm.com/book/ja/v2/Git-%e3%81%ae%e3%82%ab%e3%82%b9%e3%82%bf%e3%83%9e%e3%82%a4%e3%82%ba-Git-%e3%81%ae%e8%a8%ad%e5%ae%9a Git - Git の設定]


git stash drop実行時に、削除したコミットのSHA1が表示される。
==== .netrc ====
https://social.senooken.jp/conversation/1573147#notice-2217499


そのSHA1をapplyで指定すれば、取り込める。
Gitのパスワード入力の省略方法に~/.netrcがある。
git stash apply [stash_hash]


=== リモート ===
しかし、man netrcするとわかるけど、これはもともとFTPのためのもの。なぜGitで使えるんだ?Gitの文書で言及がない。
[https://qiita.com/mather314/items/a1536c52a2eb0426b2b5 gitの不要なブランチを消すコマンド #Git - Qiita]
git fetch -p/--prune
リモートの削除済みブランチをローカルに同期する。


=== リモートの最新タグ ===
In conversation Thursday, 21-Feb-2019 10:58:47 JST from web permalink
https:/stackoverflow.com/questions/20734181/how-to-get-list-of-latest-tags-in-remote-git


git ls-remote --tag --sort=taggerdate
せのお (妹尾 賢)せのお (妹尾 賢) in reply to


date関係のsortはオブジェクトへのアクセスが必要なので、ローカルにないとダメとか。
理由が分かった。


https:/git-scm.com/docs/git-ls-remote.html
1. Gitはhttpとhttpsの通信にcURLを使っている。


https:/stackoverflow.com/questions/10649814/get-last-git-tag-from-a-remote-repo-without-cloning
<nowiki>https://github.com/git/git/blob/master/INSTALL#L141</nowiki>


git rev-listでいけそう。
2. cURLが.netrcにも対応しているから。


https:/gist.github.com/rponte/fdc0724dd984088606b0
<nowiki>https://ec.haxx.se/usingcurl-netrc.html</nowiki>


=== core.autocrlf ===
==== core.autocrlf ====
<blockquote>warning: in the working copy of 'docker/README.md', LF will be replaced by CRLF the next time Git touches it</blockquote>Windowsでは改行にCR+LFを使うが、mac/LinuxはLFのみ。これの違いの処理のための設定がcore.autoclrlf
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向けの設定。
* true=コミット時にCRLFをLFに自動変換。チェックアウト時に逆。Windows向けの設定。
440行目: 608行目:
わかりにくい。基本はfalseで良いと思われる。
わかりにくい。基本はfalseで良いと思われる。


=== gitkの文字化け対策 ===
==== gitkの文字化け対策 ====
[https://www.pistolfly.com/weblog/2010/02/gitk.html gitkのエンコーディングを設定する - Pistolfly]
[https://www.pistolfly.com/weblog/2010/02/gitk.html gitkのエンコーディングを設定する - Pistolfly]


gitkはシステムのデフォルトエンコーディングで表示しようとするので、文字エンコーディングを指定しておく。
gitkはシステムのデフォルトエンコーディングで表示しようとするので、文字エンコーディングを指定しておく。
git config --global gui.encoding utf-8
git config --global gui.encoding utf-8
WSLなどで、日本語が表示されない場合、フォントが入っていない可能性が高い。


=== ファイル名などの文字化け対策 ===
以下のコマンドで日本語対応フォントをインストールする。
sudo apt install -y fonts-noto-cjk fonts-noto-cjk-extra fonts-ipafont
 
==== ファイル名などの文字化け対策 ====
[https://qiita.com/kumazo/items/2169e1ee7be278f82b94 Git for Windows で日本語を使いたい #Vim - Qiita]
[https://qiita.com/kumazo/items/2169e1ee7be278f82b94 Git for Windows で日本語を使いたい #Vim - Qiita]
git config --global core.quotepath false
git config --global gui.encoding utf-8
git config --global gui.encoding utf-8
git config --global core.quotepath false
 
==== core.editor ====
 
* [https://qiita.com/AX2DdNTkgzNx/items/91ebb5b428dfb88f41a5 defaultがNanoでVimに変えた話 #Git - Qiita]
* [https://qiita.com/pyon_kiti_jp/items/e4963d84585dffc7716d gitのデフォルトエディタをnanoからviに変更 #Git - Qiita]


=== 改名と修正 ===
git commitなどで使用するデフォルトのエディター設定。


* [https://qiita.com/yukimura1227/items/fbb076db61a2e43a32e3 gitでrename&modifyしたファイルのログを追跡できるようにしたい場合 #Git - Qiita]
以下の優先順位になっている。
* [https://zenn.dev/yoichi/articles/how-git-handles-renaming Gitはファイルのリネームをどう扱うか]


改名と修正を同時にすると、改名を検知できない。
* core.editor
* VISUAL環境変数
* EDITOR環境変数
* システムデフォルト


-Mオプションを指定すると、類似度で同時も検知できる。が、基本はリネーム・改名と修正は別コミットにしたほうがよさそう。
core.editorを指定するのがいい。
git config --global core.editor vi


=== squash ===
==== proxy ====
squashすると、squash対象コミットが、対象の直前のコミットに含められる。
PROXY=<nowiki>http://example.com:8080</nowiki>
git config --global http.proxy $PROXY
git config --global https.proxy $PROXY
git config --global url."https://".insteadOf git://


=== gitignore ===
==== gitignore ====
[https://git-scm.com/docs/gitignore Git - gitignore Documentation]
[https://git-scm.com/docs/gitignore Git - gitignore Documentation]


470行目: 653行目:
これで指定していないと、git addすると管理対象に入るし、untracked fileで表示が出る。git add .やディレクトリー指定で一括で管理したい場合に混ざっていると邪魔。
これで指定していないと、git addすると管理対象に入るし、untracked fileで表示が出る。git add .やディレクトリー指定で一括で管理したい場合に混ざっていると邪魔。


==== File ====
===== File =====
 
* .gitignore: ディレクトリー内。
* .gitignore: ディレクトリー内。
* $GIT_DIR/info/exclude: リポジトリー固有のローカル。
* $GIT_DIR/info/exclude: リポジトリー固有のローカル。
* core.excludesFile: ~/.gitconfig内で指定するgitignoreファイル。通常、$XDG_CONFIG_HOME/git/ignoreか$HOME/.config/git/ignore。
* core.excludesFile: ~/.gitconfig内で指定するgitignoreファイル。通常、$XDG_CONFIG_HOME/git/ignoreか$HOME/.config/git/ignore。


==== Format ====
===== Format =====
記述方法を整理する。
記述方法を整理する。


505行目: 687行目:
## /foo/*
## /foo/*
## !/foo/bar
## !/foo/bar
==== 空ディレクトリーの維持 ====
 
===== 空ディレクトリーの維持 =====
[https://stackoverflow.com/questions/115983/how-do-i-add-an-empty-directory-to-a-git-repository How do I add an empty directory to a Git repository? - Stack Overflow]
[https://stackoverflow.com/questions/115983/how-do-i-add-an-empty-directory-to-a-git-repository How do I add an empty directory to a Git repository? - Stack Overflow]


511行目: 694行目:


logなど維持したい空ディレクトリーに、以下の内容の.gitignoreを置く。
logなど維持したい空ディレクトリーに、以下の内容の.gitignoreを置く。
 
*
!.gitignore
!.gitignore
 
.gitignore以外を無視する。これで.gitignoreのみがあるので管理できる。
.gitignore以外を無視する。これで.gitignoreのみがあるので管理できる。


==== 指定ファイルのみ除外 ====
===== 指定ファイルのみ除外 =====
*
!.gitignore
!.gitignore
ディレクトリーを残す以外 (.gitignore1ファイル以外) に、サンプルファイルなど複数ファイルを残したい場合は、上記のように*で最初に全部除外して指定ファイルのみ含める。/は必要に応じてつける。
ディレクトリーを残す以外 (.gitignore1ファイル以外) に、サンプルファイルなど複数ファイルを残したい場合は、上記のように*で最初に全部除外して指定ファイルのみ含める。/は必要に応じてつける。
539行目: 720行目:
* delta
* delta
* encoding
* encoding
=== ファイルのインデックスのみ削除 ===
git rmは単独だと、gitの履歴とローカルファイルからも削除する。追跡対象から削除のみで、ローカルファイルとして残したい場合、--cachedを指定する。
git rm --cached
== Customize ==


=== Git hook ===
=== Git hook ===
579行目: 754行目:


== Other ==
== Other ==
=== .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を使っている。
<nowiki>https://github.com/git/git/blob/master/INSTALL#L141</nowiki>
2. cURLが.netrcにも対応しているから。
<nowiki>https://ec.haxx.se/usingcurl-netrc.html</nowiki>


=== submodule ===
=== submodule ===
645行目: 799行目:
** git-completion.bash
** git-completion.bash
** git-prompt.sh
** git-prompt.sh
=== 復元 ===
[https://qiita.com/generosity-naman/items/237338f8fe5b7e3b9a76 Git Stashの復元: 誤って削除されたスタッシュの復元方法 #Git-Stash - Qiita]
git stash drop実行時に、削除したコミットのSHA1が表示される。
そのSHA1をapplyで指定すれば、取り込める。
git stash apply [stash_hash]
=== 改名と修正 ===
* [https://qiita.com/yukimura1227/items/fbb076db61a2e43a32e3 gitでrename&modifyしたファイルのログを追跡できるようにしたい場合 #Git - Qiita]
* [https://zenn.dev/yoichi/articles/how-git-handles-renaming Gitはファイルのリネームをどう扱うか]
改名と修正を同時にすると、改名を検知できない。
-Mオプションを指定すると、類似度で同時も検知できる。が、基本はリネーム・改名と修正は別コミットにしたほうがよさそう。
=== squash ===
squashすると、squash対象コミットが、対象の直前のコミットに含められる。
=== ファイルのインデックスのみ削除 ===
git rmは単独だと、gitの履歴とローカルファイルからも削除する。追跡対象から削除のみで、ローカルファイルとして残したい場合、--cachedを指定する。
git rm --cached
== Remote ==
=== リモート ===
[https://qiita.com/mather314/items/a1536c52a2eb0426b2b5 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の設定があると、ローカルのブランチ名でリモートブランチも作ってくれる模様。昔はこういうオプションなかった気がする。

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