SYNOPSIS

gitfaq

DESCRIPTION

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

Configuration

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

個人名、通常は名前とファミリーネームを使用した形式を入力する必要があります。たとえば、Gitの現在のメンテナは "Junio C Hamano" (濱野 純)を使用しています。 これは、コミットするたびに保存される名前の部分になります。

この構成は、リモートサービスへの認証には影響しません。 そのためには、 git-config(1)credential.username を参照してください。

http.postBuffer は実際には何をしますか?

このオプションは、HTTPまたはHTTPSを介してデータをリモートにプッシュするときにGitが使用するバッファーのサイズを変更します。データがこのサイズより大きい場合、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 オプションを指定します。

Credentials

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が新しい資格情報の入力を求めます。資格情報を消去するには、以下の構文を使用します(ユーザー名(「author」の部分)とホスト名(「git.example.org」の部分)をあなた自身のに置き換えてください):

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

通常、これらのアカウントを区別する最も簡単な方法は、URLでユーザー名を使用することです。 たとえば、 git.example.org にアカウント authorcommitter がある場合、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) 。

Transfers

How do I sync a working tree across systems?

First, decide whether you want to do this at all. Git works best when you push or pull your work using the typical git push and git fetch commands and isn’t designed to share a working tree across systems. This is potentially risky and in some cases can cause repository corruption or data loss.

Usually, doing so will cause git status to need to re-read every file in the working tree. Additionally, Git’s security model does not permit sharing a working tree across untrusted users, so it is only safe to sync a working tree if it will only be used by a single user across all machines.

It is important not to use a cloud syncing service to sync any portion of a Git repository, since this can cause corruption, such as missing objects, changed or added files, broken refs, and a wide variety of other problems. These services tend to sync file by file on a continuous basis and don’t understand the structure of a Git repository. This is especially bad if they sync the repository in the middle of it being updated, since that is very likely to cause incomplete or partial updates and therefore data loss.

An example of the kind of corruption that can occur is conflicts over the state of refs, such that both sides end up with different commits on a branch that the other doesn’t have. This can result in important objects becoming unreferenced and possibly pruned by git gc, causing data loss.

Therefore, it’s better to push your work to either the other system or a central server using the normal push and pull mechanism. However, this doesn’t always preserve important data, like stashes, so some people prefer to share a working tree across systems.

If you do this, the recommended approach is to use rsync -a --delete-after (ideally with an encrypted connection such as with ssh) on the root of repository. You should ensure several things when you do this:

  • If you have additional worktrees or a separate Git directory, they must be synced at the same time as the main working tree and repository.

  • You are comfortable with the destination directory being an exact copy of the source directory, deleting any data that is already there.

  • The repository (including all worktrees and the Git directory) is in a quiescent state for the duration of the transfer (that is, no operations of any sort are taking place on it, including background operations like git gc and operations invoked by your editor).

    Be aware that even with these recommendations, syncing in this way has some risk since it bypasses Git’s normal integrity checking for repositories, so having backups is advised. You may also wish to do a git fsck to verify the integrity of your data on the destination system after syncing.

Common Issues

前回のコミットでミスをしました。どうすれば変更できますか?

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

バグで変更を加えましたが、それは既にメインブランチに含まれてしまっています。どうすれば元に戻すことができますか?

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

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

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

git update-index の特定の機能、つまり、assume-unchangedビットとskip-worktreeビットを使おうとするのは魅力的ですが、これらはこの目的には適切に機能しないため、このように使用しないでください。

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

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

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

フェッチまたはプルのどちらを実行すればよいか知るにはどうすればよいですか?

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

Can I use a proxy with Git?

Yes, Git supports the use of proxies. Git honors the standard http_proxy, https_proxy, and no_proxy environment variables commonly used on Unix, and it also can be configured with http.proxy and similar options for HTTPS (see git-config(1)). The http.proxy and related options can be customized on a per-URL pattern basis. In addition, Git can in theory function normally with transparent proxies that exist on the network.

For SSH, Git can support a proxy using OpenSSH’s ProxyCommand. Commonly used tools include netcat and socat. However, they must be configured not to exit when seeing EOF on standard input, which usually means that netcat will require -q and socat will require a timeout with something like -t 10. This is required because the way the Git SSH server knows that no more requests will be made is an EOF on standard input, but when that happens, the server may not have yet processed the final request, so dropping the connection at that point would interrupt that request.

An example configuration entry in ~/.ssh/config with an HTTP proxy might look like this:

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

Note that in all cases, for Git to work properly, the proxy must be completely transparent. The proxy cannot modify, tamper with, or buffer the connection in any way, or Git will almost certainly fail to work. Note that many proxies, including many TLS middleboxes, Windows antivirus and firewall programs other than Windows Defender and Windows Firewall, and filtering proxies fail to meet this standard, and as a result end up breaking Git. Because of the many reports of problems and their poor security history, we recommend against the use of these classes of software and devices.

Merging and Rebasing

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

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

Gitが2つのブランチ間で通常のマージを行う場合、正確に3者が考慮されます。2つのブランチと、通常は2つのコミットの共通の祖先である「マージベース」(merge base)と呼ばれる3番目のコミットです。マージの結果は、マージベースと各headの間の変更の合計です。2つのブランチを通常のマージコミットでマージすると、新しい共通の祖先を持つ、新しいコミットが発生し、再度マージされるときはそれが最終的なマージベースになります。そうすると、Gitは、マージベースの前に発生した変更を考慮する必要がないため、以前に解決した競合を再解決する必要がありません。

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

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

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

デフォルトでは、Gitがマージを行うとき、それは「ort」戦略と呼ばれる戦略を使用します。これは、派手な3者間マージ(fancy three-way merge)を行います。 このような場合、Gitはマージを実行するときに、正確に3つのポイントを考慮します。2つのheadと、通常はこれらのコミットの共通の祖先である「マージベース」(merge base)と呼ばれる3番目のポイントです。 Gitは、これらのブランチで発生した履歴や個々のコミットをまったく考慮しません。

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

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

Hooks

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

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

pre-commit フック(または、コミットメッセージの場合は commit-msg フック)を使用してこれらをチェックするのが一般的です。これは、単独の開発者として作業していて、ツールが役立つことを望んでいる場合に最適です。ただし、開発者のマシンでフックを使用することは、ユーザーが(他のさまざまな方法の中でも)気付かれることなく --no-verify でこれらのフックをバイパスできるため、ポリシーコントロールとしては効果的ではありません。 Gitは、ユーザーがローカルリポジトリを管理していることを前提としており、これを防止したり、ユーザーを攻撃したりすることはありません。

さらに、一部の上級ユーザーは、「pre-commit」フックが、一時的なコミットを使用して進行中の作業をステージングしたり、修正コミットを作成したりするワークフローの障害であると感じているため、とにかくこれらの種類のチェックはサーバーに押しやることをお勧めします。

Cross-Platform Issues

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

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

これを行うには、 working-tree-encoding 属性を使用して gitattributes(5) パターンを指定できます。たとえば、以下のパターンは、Windowsで一般的なエンコーディングである UTF-16LE-BOM を使用するようにすべてのC言語ファイルを設定します:

*.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はデフォルトで、既存の行ではなく、新しい行にのみ末尾の空白を表示します。

You can store the files in the repository with Unix line endings and convert them automatically to your platform’s line endings. To do that, set the configuration option core.eol to native and see the question on recommended storage settings for information about how to configure files as text or binary.

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

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

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

ファイルが1つだけになるように、ファイルの1つを削除することをお勧めします。これは、以下のようなコマンド(2つのファイル AFile.txt と`afile.txt` を想定)を使用して、他の点ではクリーンな作業ツリーで実行できます:

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

これにより、ディスクへの変更は回避され、追加のファイルは削除されます。プロジェクトでは、この問題が再発しないように、すべて小文字の名前などの命名規則を採用することをお勧めします。このような規則は、 pre-receive フックを使用して、または継続的インテグレーション(CI)システムにてチェックできます。

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

$ git add --renormalize .
Gitにファイルを保存するための推奨の方法は何ですか?

Gitはあらゆるタイプのあらゆるファイルを保存および処理できますが、他の設定よりもうまく機能する設定がいくつかあります。一般に、テキストファイルは、LF(Unixスタイル)で終わるバイト順マーク(BOM)なしでUTF-8に保存することをお勧めします。また、コミットメッセージでUTF-8(ここでもBOMなし)を使用することをお勧めします。これらは、プラットフォーム間や git diffgit merge などのツールで最適に機能する設定です。

同様に、バイナリ依存関係(共有ライブラリやJARファイルなど)を格納したり、リポジトリに製品をビルドしたりすることは、通常はお勧めしません。依存関係とビルド製品は、リポジトリに保存されている参照、URL、ハッシュのみを使用して、アーティファクトサーバーまたはパッケージサーバーに保存するのが最適です。

We also recommend setting a gitattributes(5) file to explicitly mark which files are text and which are binary. If you want Git to guess, you can set the attribute text=auto.

With text files, Git will generally ensure that LF endings are used in the repository. The core.autocrlf and core.eol configuration variables specify what line-ending convention is followed when any text file is checked out. You can also use the eol attribute (e.g., eol=crlf) to override which files get what line-ending treatment.

For example, generally shell files must have LF endings and batch files must have CRLF endings, so the following might be appropriate in some projects:

# By default, guess.
*       text=auto
# Mark all C files as text.
*.c     text
# Ensure all shell files have LF endings and all batch files have CRLF
# endings in the working tree and both have LF in the repo.
*.sh text eol=lf
*.bat text eol=crlf
# Mark all JPEG files as binary.
*.jpg   binary

これらの設定は、ツールがパッチなどの出力に適切な形式を選択するのに役立ち、プラットフォームに適切な行末コードでファイルがチェックアウトされます。

GIT

Part of the git(1) suite