日本語 ▾ トピック ▾ 最新バージョン ▾ gitfaq は 2.46.0 で最終更新されました

名前

gitfaq - Git の使用に関するよくある質問

概要

gitfaq

説明

この FAQ の例は、bashdash のような標準的な POSIX シェルと、ホスティングプロバイダー git.example.orgauthor アカウントを持つユーザー A U Thor を想定しています。

設定

user.name には何を入れるべきですか?

一般的に、与えられた名前と姓を使った形式で、あなたの個人名を入れるべきです。例えば、Git の現在のメンテナは「Junio C Hamano」を使用しています。これは、あなたが行うすべてのコミットに保存される名前の部分になります。

この設定はリモートサービスへの認証には影響しません。それについては、git-config[1]credential.username を参照してください。

http.postBuffer は実際には何をするのですか?

このオプションは、Git が HTTP または HTTPS 経由でリモートにデータをプッシュする際に使用するバッファのサイズを変更します。データがこのサイズより大きい場合、Git の HTTP サポートを処理する libcurl は、プッシュされるデータのサイズが事前にわからないため、チャンク転送エンコーディングを使用します。

リモートサーバーまたは途中のプロキシが HTTP/1.1 (チャンク転送エンコーディングを導入したもの) をサポートしていないか、チャンクデータで壊れていることが分かっている場合を除き、この値をデフォルトのサイズにしても問題ありません。これは一般的なプッシュの問題に対する解決策として (誤って) 提案されることが多いですが、ほとんどすべてのサーバーとプロキシが少なくとも HTTP/1.1 をサポートしているため、この値を大きくしてもほとんどのプッシュの問題は解決しません。HTTP/1.1 とチャンク転送エンコーディングを正しくサポートしていないサーバーやプロキシは、今日のインターネットでは多くのトラフィックを破壊するため、あまり有用ではありません。

この値を増やすと、Git が HTTP または HTTPS 経由で行うすべての関連プッシュで消費されるメモリが増えることに注意してください。これは、バッファ全体が使用されるかどうかに関わらず割り当てられるためです。したがって、異なる値が必要だと確信している場合を除き、デフォルトのままにしておくのが最善です。

別のエディターを設定するにはどうすればよいですか?

Git にエディターを特に指定していない場合、デフォルトでは VISUAL または EDITOR 環境変数で設定したエディターが使用されます。どちらも指定されていない場合は、システムのデフォルト (通常は vi) が使用されます。vi を使いにくいと感じる人や、別のエディターを好む人もいるため、使用するエディターを変更することが望ましい場合があります。

ほとんどのプログラムで必要な汎用エディターを設定したい場合は、シェル設定 (例: ~/.bashrc または ~/.zshenv) を編集して、EDITOR または VISUAL 環境変数に適切な値を設定する行を含めることができます。例えば、nano エディターを好む場合は、次のように記述できます。

export VISUAL=nano

Git 専用のエディターを設定したい場合は、core.editor 設定値または GIT_EDITOR 環境変数を設定できます。これらのオプションが参照される順序の詳細については、git-var[1] を参照してください。

どの場合でも、エディターの値はシェルに渡されるため、スペースを含む引数は適切に引用符で囲む必要があることに注意してください。さらに、エディターが通常呼び出し時に端末からデタッチされる場合、そうしないようにする引数を指定する必要があります。そうしないと、Git は変更を認識しません。Windows でこれらの両方の問題に対処する設定の例は、ファイル名をスペースで引用符で囲み、プロセスをバックグラウンド化しないように --nofork オプションを指定する設定 "C:\Program Files\Vim\gvim.exe" --nofork です。

認証情報

HTTP 経由でプッシュする際に認証情報を指定するにはどうすればよいですか?

最も簡単な方法は、credential.helper 設定を介して認証ヘルパーを使用することです。ほとんどのシステムは、システム認証マネージャーと統合するための標準的な選択肢を提供します。例えば、Git for Windows は wincred 認証マネージャーを提供し、macOS には osxkeychain 認証マネージャーがあり、標準のデスクトップ環境を持つ Unix システムは libsecret 認証マネージャーを使用できます。これらはすべて、パスワードやトークンを安全に保つために、暗号化されたストアに認証情報を保存します。

さらに、ホームディレクトリのファイルに保存する store 認証マネージャーや、認証情報を永続的に保存しないが、一定期間プロンプトを表示しない cache 認証マネージャーも使用できます。

プロンプトが表示されたときにパスワードを入力することもできます。パスワード (パーセントエンコードする必要がある) を URL に含めることも可能ですが、これは特に安全ではなく、認証情報の偶発的な漏洩につながる可能性があるため、推奨されません。

環境変数からパスワードやトークンを読み取るにはどうすればよいですか?

credential.helper 設定オプションは、標準出力に認証プロトコルを出力する任意のシェルコマンドも受け入れることができます。これは、例えば、認証情報をコンテナに渡す場合に便利です。

このようなシェルコマンドは、オプション値を感嘆符で始めることで指定できます。パスワードまたはトークンが GIT_TOKEN に保存されている場合、次のコマンドを実行して認証ヘルパーを設定できます。

$ git config credential.helper \
	'!f() { echo username=author; echo "password=$GIT_TOKEN"; };f'
認証マネージャーに保存したパスワードまたはトークンを変更するにはどうすればよいですか?

通常、パスワードまたはトークンが無効な場合、Git はそれを消去し、新しいパスワードまたはトークンの入力を求めます。ただし、常にそうとは限らない場合があります。パスワードまたはトークンを変更するには、既存の認証情報を消去すると、Git は新しい認証情報の入力を求めます。認証情報を消去するには、次のような構文を使用します (ユーザー名とホスト名を置き換えてください)。

$ echo url=https://author@git.example.org | git credential reject
HTTP を使用して同じホスティングプロバイダーで複数のアカウントを使用するにはどうすればよいですか?

通常、これらのアカウントを区別する最も簡単な方法は、URL でユーザー名を使用することです。例えば、git.example.orgauthorcommitter のアカウントがある場合、https://author@git.example.org/org1/project1.githttps://committer@git.example.org/org2/project2.git の URL を使用できます。これにより、認証ヘルパーを使用すると、アカウントの正しい認証情報を自動的に検索しようとします。すでにリモートが設定されている場合は、git remote set-url origin https://author@git.example.org/org1/project1.git のように URL を変更できます (詳細については git-remote[1] を参照してください)。

SSH を使用して同じホスティングプロバイダーで複数のアカウントを使用するにはどうすればよいですか?

SSH をサポートするほとんどのホスティングプロバイダーでは、単一のキーペアがユーザーを一意に識別します。したがって、複数のアカウントを使用するには、各アカウントにキーペアを作成する必要があります。比較的新しい OpenSSH バージョンを使用している場合は、ssh-keygen -t ed25519 -f ~/.ssh/id_committer のようにして新しいキーペアを作成できます。その後、公開キー (この場合、~/.ssh/id_committer.pub; .pub に注意) をホスティングプロバイダーに登録できます。

ほとんどのホスティングプロバイダーはプッシュに単一の SSH アカウントを使用します。つまり、すべてのユーザーは git アカウント (例: git@git.example.org) にプッシュします。プロバイダーがその場合、SSH で複数のエイリアスを設定して、どのキーペアを使用するかを明確にすることができます。例えば、~/.ssh/config に次のように記述し、適切な秘密キーファイルを置き換えることができます。

# This is the account for author on git.example.org.
Host example_author
	HostName git.example.org
	User git
	# This is the key pair registered for author with git.example.org.
	IdentityFile ~/.ssh/id_author
	IdentitiesOnly yes
# This is the account for committer on git.example.org.
Host example_committer
	HostName git.example.org
	User git
	# This is the key pair registered for committer with git.example.org.
	IdentityFile ~/.ssh/id_committer
	IdentitiesOnly yes

次に、プッシュ URL を git@example.org の代わりに git@example_author または git@example_committer を使用するように調整できます (例: git remote set-url git@example_author:org1/project1.git)。

転送

複数のシステム間で作業ツリーを同期するにはどうすればよいですか?

まず、そもそもこれを実行するかどうかを決定してください。Git は、通常の git push および git fetch コマンドを使用して作業をプッシュまたはプルするときに最も効果を発揮し、システム間で作業ツリーを共有するように設計されていません。これは潜在的にリスクがあり、場合によってはリポジトリの破損やデータ損失を引き起こす可能性があります。

通常、そうすると git status が作業ツリー内のすべてのファイルを再読み込みする必要が生じます。さらに、Git のセキュリティモデルは、信頼できないユーザー間での作業ツリーの共有を許可しないため、すべてのマシンで単一のユーザーのみが使用する場合にのみ作業ツリーを安全に同期できます。

Git リポジトリのいかなる部分もクラウド同期サービスを使用して同期しないことが重要です。オブジェクトの欠落、ファイルの変更や追加、壊れた参照、その他さまざまな問題など、破損を引き起こす可能性があるためです。これらのサービスは、継続的にファイルごとに同期する傾向があり、Git リポジトリの構造を理解していません。これは、リポジトリが更新中に同期される場合に特に悪く、不完全な更新や部分的な更新、したがってデータ損失を引き起こす可能性が非常に高いためです。

発生しうる破損の種類の例として、参照の状態に関する競合があり、両側が互いが持っていないブランチ上で異なるコミットを持つことになる場合があります。これにより、重要なオブジェクトが参照されなくなり、git gc によってプルーニングされる可能性があり、データ損失につながります。

したがって、作業を他のシステムまたは中央サーバーに通常のプッシュおよびプルメカニズムを使用してプッシュする方が良いでしょう。ただし、これはstashのような重要なデータを常に保持するわけではないため、システム間で作業ツリーを共有することを好む人もいます。

これを行う場合、推奨されるアプローチは、リポジトリのルートで rsync -a --delete-after (理想的には ssh のような暗号化された接続を使用) を使用することです。これを行う際には、いくつかのことを確認する必要があります。

  • 追加の作業ツリーまたは個別の Git ディレクトリがある場合、それらはメインの作業ツリーおよびリポジトリと同時に同期する必要があります。

  • 宛先ディレクトリがソースディレクトリと正確に同じコピーになることを許容できること、既にそこにあるデータはすべて削除されることを許容できること。

  • 転送中は (すべての作業ツリーと Git ディレクトリを含む) リポジトリが静止状態であること (つまり、git gc のようなバックグラウンド操作やエディターによって呼び出される操作を含め、いかなる種類の操作も行われていないこと)。

    これらの推奨事項に従っても、この方法での同期にはGitの通常のリポジトリ整合性チェックをバイパスするため、リスクがあることに注意してください。そのため、バックアップを取ることをお勧めします。同期後、宛先システムでデータの整合性を検証するために git fsck を実行することも検討してください。

一般的な問題

最後のコミットで間違いを犯しました。どうすれば変更できますか?

作業ツリーに適切な変更を加え、必要に応じて git add <ファイル> または git rm <ファイル> を実行してステージングし、その後 git commit --amend を実行します。変更はコミットに含まれ、コミットメッセージを再度編集するよう求められます。元のメッセージをそのまま使用したい場合は、git commit--no-edit オプションを追加するか、エディターが開いたときに保存して終了するだけです。

バグのある変更を行ってしまい、それがメインブランチに含まれてしまいました。どのように元に戻すべきですか?

これに対処する通常の解決策は、git revert を使用することです。これにより、元の変更が行われ、貴重な貢献であったという履歴は保持されますが、元の変更に問題があったため、それらの変更を元に戻す新しいコミットも導入されます。リバートのコミットメッセージは、リバートされたコミットを示し、通常はリバートが行われた理由を説明するために編集されます。

追跡対象ファイルの変更を無視するにはどうすればよいですか?

Git にはこれを行う方法がありません。その理由は、Git がこのファイルを上書きする必要がある場合(チェックアウト時など)、ファイルへの変更が貴重で保持すべきなのか、それとも無関係で安全に破棄できるのかがわからないためです。したがって、安全な方法を取り、常にそれらを保持する必要があります。

git update-index の特定の機能、すなわち assume-unchanged および skip-worktree ビットを使用しようとすると、この目的のために正しく機能せず、このように使用すべきではありません。

設定ファイルを変更することが目的の場合、リポジトリにチェックインされたファイルをテンプレートまたはデフォルトのセットとして持ち、それを横にコピーして適切に修正できることが役立つことがよくあります。この2番目の修正されたファイルは、誤ってコミットされるのを防ぐために通常は無視されます。

Git に様々なファイルを無視するよう指示しましたが、それらがまだ追跡されています。

gitignore ファイルは、Git によって追跡されていない特定のファイルが追跡されないようにします。しかし、.gitignore に追加する前に特定のファイルが追跡されていた場合、それらはまだ追跡されたままになります。ファイルを追跡解除して無視するには、git rm --cached <ファイル/パターン> を使用し、<ファイル> に一致するパターンを .gitignore に追加します。詳細については、gitignore[5] を参照してください。

フェッチとプル、どちらを行うべきかどうやって判断すればよいですか?

フェッチは、リモートリポジトリからの最新の変更を、作業ツリーや現在のブランチを変更せずにコピーして保存します。その後、自由に上流の変更を検査、マージ、リベース、または無視することができます。プルは、フェッチの直後にマージまたはリベースを実行するものです。git-pull[1] を参照してください。

Git でプロキシを使用できますか?

はい、Git はプロキシの使用をサポートしています。Git は Unix で一般的に使用される標準の http_proxyhttps_proxyno_proxy 環境変数を尊重し、HTTPS 用の http.proxy と同様のオプションでも設定できます ( git-config[1] を参照)。http.proxy および関連オプションは、URL パターンごとにカスタマイズできます。さらに、Git は理論上、ネットワーク上に存在する透過型プロキシと正常に連携できます。

SSHの場合、GitはOpenSSHのProxyCommandを使ってプロキシをサポートできます。netcatsocatといったツールが一般的に使われます。ただし、これらは標準入力でEOFを見ても終了しないように設定する必要があります。これは通常、netcatには-qが必要で、socatには-t 10のようなタイムアウトが必要であることを意味します。これは、Git SSHサーバーがこれ以上リクエストがないことを知る方法は標準入力のEOFですが、その時点でサーバーが最終リクエストをまだ処理していない可能性があり、その時点で接続を切断するとそのリクエストが中断されるためです。

~/.ssh/config の HTTP プロキシを含む設定エントリの例は次のようになります。

Host git.example.org
    User git
    ProxyCommand socat -t 10 - PROXY:proxy.example.org:%h:%p,proxyport=8080

すべての場合において、Git が正しく機能するためには、プロキシが完全に透過的である必要があります。プロキシは、接続を変更、改ざん、またはバッファリングしてはならず、そうしないと Git はほぼ確実に機能しなくなります。多くのプロキシ、多くの TLS ミドルボックス、Windows Defender および Windows Firewall 以外の Windows のアンチウイルスおよびファイアウォールプログラム、およびフィルタリングプロキシは、この標準を満たしておらず、その結果 Git を破損させることに注意してください。多くの問題報告とその貧弱なセキュリティ履歴のため、これらの種類のソフトウェアおよびデバイスの使用は推奨しません。

マージとリベース

スクワッシュマージで長期間のブランチをマージする際に、どのような問題が発生する可能性がありますか?

一般的に、スクワッシュマージを使用して2つのブランチを複数回マージする場合、さまざまな問題が発生する可能性があります。これには、git log 出力、GUI、または範囲を表す ... 記法を使用するときに余分なコミットが表示されることや、競合を繰り返し再解決する必要がある可能性などが含まれます。

Git が2つのブランチ間で通常のマージを行う場合、3つの点だけを考慮します。つまり、2つのブランチと、通常はコミットの共通の祖先である*マージベース*と呼ばれる3番目のコミットです。マージの結果は、マージベースと各ヘッド間の変更の合計です。通常のコミットで2つのブランチをマージすると、新しい共通の祖先ができたため、再度マージするときにその結果が新しいマージベースになります。Git はマージベースより前に発生した変更を考慮する必要がないため、以前に解決した競合を再解決する必要はありません。

スクワッシュマージを実行すると、マージコミットは作成されません。代わりに、一方の変更が通常のコミットとして他方に適用されます。これは、これらのブランチのマージベースが変更されていないことを意味するため、Git が次のマージを実行するときに、前回考慮したすべての変更と新しい変更を考慮します。つまり、競合を再解決する必要がある場合があります。同様に、git diffgit log、または GUI で ... 記法を使用すると、元のマージベース以降のすべての変更が表示されます。

結果として、2つの長期間のブランチを繰り返しマージしたい場合は、常に通常のコミットを使用するのが最善です。

2つのブランチで変更を行い、そのうち1つで元に戻した場合、なぜそれらのブランチのマージにその変更が含まれるのですか?

デフォルトでは、Git はマージを行う際に、洗練されたスリーウェイマージを行う ort 戦略を使用します。このような場合、Git はマージを実行する際に、2つのヘッドと、通常はそれらのコミットの共通の祖先である*マージベース*と呼ばれる3番目の点のちょうど3つの点を考慮します。Git は、それらのブランチで発生した履歴や個々のコミットを一切考慮しません。

その結果、両方の側で変更があり、一方の側でその変更が元に戻された場合、結果はその変更を含めることになります。これは、コードが一方の側で変更され、他方の側では実質的な変更がないためであり、このシナリオでは Git は変更を採用します。

これが問題となる場合、代わりにリベースを行うことができます。元に戻したブランチをもう一方のブランチにリベースします。このシナリオでのリベースは、リベースが個々のコミット(元に戻すコミットを含む)を適用するため、変更を元に戻します。リベースは履歴を書き換えるため、公開されたブランチをリベースすることは、それに慣れていることを確信している場合を除き避けるべきであることに注意してください。詳細については、git-rebase[1] の NOTES セクションを参照してください。

フック

ユーザーが特定の変更を行うのを防ぐには、フックをどのように使用すればよいですか?

これらの変更を行う唯一安全な場所は、リモートリポジトリ (つまり Git サーバー) であり、通常は pre-receive フックまたは継続的インテグレーション (CI) システム内です。これらはポリシーを効果的に強制できる場所です。

これらのことをチェックするために pre-commit フック (またはコミットメッセージの場合は commit-msg フック) を使用することが一般的ですが、これは単独の開発者として作業していてツールに助けてもらいたい場合に非常に役立ちます。ただし、開発者マシンでフックを使用することは、ポリシー制御としては効果がありません。なぜなら、ユーザーは --no-verify を使用して (その他さまざまな方法で) これらのフックを気づかれずにバイパスできるためです。Git は、ユーザーが自分のローカルリポジトリを制御していると仮定しており、これを阻止したり、ユーザーの密告を試みたりしません。

さらに、一部の高度なユーザーは、作業中のものをステージングするための仮コミットや修正コミットを作成するワークフローにとって pre-commit フックが妨げになると感じているため、これらの種類のチェックはとにかくサーバーにプッシュする方が良いでしょう。

クロスプラットフォームの問題

私は Windows を使用しており、テキストファイルがバイナリとして検出されます。

Git はテキストファイルを UTF-8 で保存するときに最も効果を発揮します。Windows の多くのプログラムは UTF-8 をサポートしていますが、一部のプログラムはサポートしておらず、Git がバイナリとして検出するリトルエンディアン UTF-16 形式のみを使用します。プログラムで UTF-8 を使用できない場合でも、リポジトリにこれらのファイルを UTF-8 で保存しながら、ファイルがチェックアウトされるエンコーディングを示す作業ツリーエンコーディングを指定できます。これにより、git-diff[1] などのツールが期待どおりに機能し、同時にツールも機能します。

これを行うには、working-tree-encoding 属性を持つ gitattributes[5] パターンを指定します。例えば、次のパターンはすべての C ファイルを UTF-16LE-BOM (Windows で一般的なエンコーディング) を使用するように設定します。

*.c	working-tree-encoding=UTF-16LE-BOM

これを有効にするには git add --renormalize を実行する必要があります。これらの変更を複数のプラットフォームで使用されるプロジェクトで行う場合、リポジトリ内の .gitattributes ファイルでこれを行うと、リポジトリのすべてのユーザーに適用されるため、ユーザーごとの設定ファイルまたは $GIT_DIR/info/attributes 内のファイルでこれを行うのが望ましいでしょう。

改行コードの正規化に関する情報も次のエントリを参照し、属性ファイルの詳細については gitattributes[5] を参照してください。

私は Windows を使用しており、git diff でファイルが末尾に ^M を持っていると表示されます。

デフォルトでは、Git はファイルを Unix スタイルの改行コードで保存することを想定しています。そのため、Windows の改行コードの一部であるキャリッジリターン (^M) は、後続の空白文字と見なされるため表示されます。Git はデフォルトで、既存の行ではなく新しい行にのみ後続の空白文字を表示します。

ファイルをリポジトリに Unix 改行コードで保存し、プラットフォームの改行コードに自動的に変換することができます。これを行うには、設定オプション core.eolnative に設定し、ファイルをテキストまたはバイナリとして設定する方法については、推奨される保存設定に関する質問を参照してください。

行末のキャリッジリターンを削除したくない場合は、core.whitespace 設定でこの動作を制御することもできます。

なぜ常に変更されているファイルがあるのですか?

内部的には、Git は常にファイル名をバイトシーケンスとして保存し、エンコーディングや大文字・小文字の畳み込みは行いません。しかし、Windows と macOS はデフォルトでファイル名の大文字・小文字の畳み込みを行います。その結果、名前が大文字・小文字のみが異なる複数のファイルやディレクトリが存在する可能性があります。Git はこれを問題なく処理できますが、ファイルシステムはこれらのファイルのうちの1つしか保存できないため、Git が他のファイルを読み込んでその内容を確認しようとすると、変更されているように見えます。

ファイルは1つだけになるように、いずれかのファイルを削除するのが最善です。これは、他にクリーンな作業ツリーで次のようなコマンド(2つのファイル AFile.txtafile.txt を仮定)を使用して行えます。

$ git rm --cached AFile.txt
$ git commit -m 'Remove files conflicting in case'
$ git checkout .

これはディスクに触れずに、追加のファイルを削除します。プロジェクトでは、この問題が再発するのを避けるために、すべて小文字の名前などの命名規則を採用することを好むかもしれません。このような規則は、pre-receive フックを使用するか、継続的インテグレーション(CI)システムの一部としてチェックできます。

システムでスマッジまたはクリーンフィルターが使用されているにもかかわらず、以前にスマッジまたはクリーンフィルターを実行せずにコミットされたファイルがある場合にも、どのプラットフォームでも永続的に変更されたファイルが発生する可能性があります。これを修正するには、他にクリーンな作業ツリーで次を実行します。

$ git add --renormalize .

GIT

git[1]スイートの一部

scroll-to-top