Git

提供:senooken JP Wiki
2025年1月14日 (火) 11:25時点におけるSenooken (トーク | 投稿記録)による版 (誤ったブランチへのコミットの付け直し)

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

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

PR後のブランチ更新

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

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

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

View

log

  • 逆順表示: --reverse
  • 差分表示: -p

Other

親コミットの参照

Git - リビジョンの選択

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

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

Commit

マージコミット後のコミット追加

マージコミット後に次の開発作業を始めることが多い。が、直後の初回のコミットを追加したい場合困る。

git rebase -iにすると、コミットが残るから。編集はできるが、その直前にコミットの追加ができない。マージコミットは扱いが特殊で直接rebaseで編集できない。

しかたないので、該当コミットでブランチを作成して、コミット。その後、既存の修正ブランチをrebaseでそのコミットの後にくっつける。これでいける。

コミットオプション

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 revert -m 1 マージコミット git reset --hard HEAD~1 # マージコミット前 どちらか。

stash

復元

Git Stashの復元: 誤って削除されたスタッシュの復元方法 #Git-Stash - Qiita

git stash drop実行時に、削除したコミットのSHA1が表示される。

そのSHA1をapplyで指定すれば、取り込める。 git stash apply [stash_hash]

リモート

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

差分ファイル抽出

情報源: 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/

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

ファイル名などの文字化け対策

Git for Windows で日本語を使いたい #Vim - Qiita git config --global core.quotepath false git config --global gui.encoding utf-8

改名と修正

改名と修正を同時にすると、改名を検知できない。

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

差分無視

git diffの--ignoreオプションにおけるスペース、タブ、改行の扱いを理解する #Git - Qiita

-wでインデント違いを無視してくれる。

squash

squashすると、squash対象コミットが、対象の直前のコミットに含められる。

gitignore

Git - gitignore Documentation

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 以外のすべてを除外

/* !/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 rmは単独だと、gitの履歴とローカルファイルからも削除する。追跡対象から削除のみで、ローカルファイルとして残したい場合、--cachedを指定する。 git rm --cached

gitk

problem

ブランチ名が長いと、右クリックしにくい

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'

Other

他のブランチとの同一化

git diff HEAD master | patch -p 1

patchの他にgit applyでもいい。

.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

git checkoutなしのmerge

gitでブランチをマージする場合、基本はマージの取り込み元ブランチに移動してから、対象ブランチを取り込む必要がある。

これは、3wayマージなどのために、マージの元ファイルが必要だからとのこと。

ただ、毎回切り替えるのが面倒くさい。ブランチ同士でのマージが一応可能。

git fetch . src:dst

ただし、このコマンドはfast-fowardsマージの場合だけ。rebase相当。それ以外は上書きされるので、手動マージが必要。注意が必要。

スクリプトの自動処理などで使う感じ。

誤ったブランチへのコミットの付け直し

  • [初心者向け Gitで間違ったブランチにしたコミットを別ブランチに付け替える | DevelopersIO]
  • [Git誤ったブランチで実施した変更を正しいブランチに移動する | DevelopersIO]

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

いくつか方法がある。

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

2番目の方法がいいかも。

git rebase --ontoでもいけたかもしれない。