Git
日本語 ▾ トピック ▾ 最新バージョン ▾ 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 でこれらの両方の問題に対処する設定の例は、"C:\Program Files\Vim\gvim.exe" --nofork の設定です。これは、スペースを含むファイル名を引用符で囲み、プロセスをバックグラウンドにしないように --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 のアカウントがある場合は、URL https://author@git.example.org/org1/project1.githttps://committer@git.example.org/org2/project2.git を使用できます。このようにすると、認証情報ヘルパーを使用するときに、アカウントの正しい認証情報を自動的に検索しようとします。リモートがすでに設定されている場合は、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 <file>またはgit rm <file>を必要に応じて実行してステージングし、次にgit commit --amendを実行します。変更がコミットに含まれ、コミットメッセージを再度編集するように求められます。元のメッセージをそのまま使用する場合は、git commitに追加で--no-editオプションを使用するか、エディタが開いたときに保存して終了するだけです。

バグのある変更を加えてしまい、それがメインブランチに含まれてしまいました。どうすれば元に戻せますか?

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

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

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

git update-indexの特定の機能、つまりassume-unchangedビットとskip-worktreeビットを使用しようとするのは魅力的ですが、これらはこの目的には適切に機能せず、この方法で使用すべきではありません。

目的が構成ファイルを変更することである場合、テンプレートまたはデフォルトのセットであるファイルをリポジトリにチェックインし、必要に応じてコピーして変更すると役立つ場合があります。この2番目の変更されたファイルは、誤ってコミットするのを防ぐために通常は無視されます。

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

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

fetchまたはpullを実行する必要があるかどうかを判断するにはどうすればよいですか?

fetchは、作業ツリーまたは現在のブランチを変更せずに、リモートリポジトリからの最新の変更のコピーを保存します。その後、都合の良いときに、アップストリームの変更を検査、マージ、トップにリベース、または無視できます。pullは、fetchの直後にマージまたはリベースのいずれかが続くことで構成されます。git-pull[1]を参照してください。

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

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

SSHの場合、GitはOpenSSHのProxyCommandを使用してプロキシをサポートできます。一般的に使用されるツールには、netcatおよびsocatが含まれます。ただし、標準入力でEOFを検出したときに終了しないように構成する必要があります。これは通常、netcat-qを必要とし、socat-t 10のようなタイムアウトを必要とすることを意味します。これは、Git SSHサーバーがこれ以上要求がないことを認識する方法が標準入力でのEOFであるためですが、その場合、サーバーが最終要求をまだ処理していない可能性があり、その時点で接続をドロップすると、その要求が中断されるため、必須です。

HTTPプロキシを使用した~/.ssh/configの構成エントリの例は次のようになります。

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

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

マージとリベース

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

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

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

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

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

2つのブランチで変更を加え、一方ではそれをリバートした場合、それらのブランチのマージになぜその変更が含まれるのですか?

デフォルトでは、Gitがマージを行う際、ortと呼ばれる戦略を使用します。これは、高度な三方向マージを行います。この場合、Gitがマージを実行する際、正確に3つのポイントを考慮します。それは、2つのヘッドと、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をサポートしていますが、一部はサポートしておらず、リトルエンディアンのUTF-16形式のみを使用しています。これはGitがバイナリとして検出します。プログラムでUTF-8を使用できない場合は、リポジトリにこれらのファイルをUTF-8として保存したまま、ファイルがチェックアウトされる際に使用するエンコーディングを示すワーキングツリーのエンコーディングを指定できます。これにより、git-diff[1]などのツールが期待どおりに動作し、ツールも引き続き動作できます。

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

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

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

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

Windowsを使用していますが、git diffでファイルの末尾に^Mが表示されます。

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

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

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

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

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

1つのファイルのみになるように、ファイルの1つを削除するのが最適です。それ以外はクリーンなワーキングツリーで、次のコマンドのようなものを使用してこれを行うことができます(AFile.txtafile.txtの2つのファイルがあると仮定します)。

$ 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