[解決済み】Gitの言う「私たち」とは誰のことで、「彼ら」とは誰のことなのか?
質問
Git のリベースの後やその他の状況下で、いくつかのファイルに
弊社で削除
の中にある
git status
を報告します。誰が
私たち
Gitによれば、その理由とは?
このブランチに座っている私のことを指しているのでしょうか、そしてそれは私のために働いているのでしょうか?それとも、私自身と、私がリベースしているブランチで作業している人たちを指しているのでしょうか?
解決方法は?
(これは、"git rebaseはどのように動作し、それによって何が起こっているのか、という質問に対する答えでもあります("))
すべての場合において
-
"私たち"
(または
"ours"
) = 現在チェックアウトされているコミット (
HEAD
) を実行した時点で、gitはそのアクションを で、これが衝突を引き起こす(これについては後で詳しく説明します)。 - 彼ら" (または "theirs" ) = もう一方のコミット、git がチェックアウトしていないもの gitがアクションを起こした瞬間に があり、それがコンフリクトの原因となります(これについては後述します)。
重要です。
HEAD
を実行した時点で、衝突を引き起こすアクションは、必ずしも
HEAD
は、gitコマンドを入力した瞬間のものです。これは理解しておく必要があります。Git はいくつかのチェックアウトを行い
HEAD
(どのコミットがチェックアウトされたか) を実行する前に衝突が発生し、素人目には "us" と "them" が入れ替わった、あるいは逆に見えることになります。
4つのケースの詳細: マージ、チェリーピック、リベース、リバート。
-
git merge
(直感的)です。-
サンプルコマンドです。
git checkout master git merge feature_branch # merge feature_branch into master
-
"us"/"ours"。
=
HEAD
である。master
ブランチにいたためmaster
を実行した時にgit merge feature_branch
. -
"they"/"theirs"。
=
feature_branch
にマージするブランチです。master
.
-
サンプルコマンドです。
-
git cherry-pick
(直感的な)。-
サンプルコマンドです。
git checkout feature_branch git cherry-pick some_commit # apply some_commit to feature_branch
-
"us"/"ours"。
=
HEAD
である。feature_branch
ブランチにいたためfeature_branch
を実行した時にgit cherry-pick some_commit
. -
"they"/"theirs"。
=
some_commit
にチェリーピックしているコミットです。feature_branch
.
-
サンプルコマンドです。
-
git rebase
(直感に反しているが、仕組みを理解すれば全く納得がいく)。-
サンプルコマンドです。
git checkout feature_branch git rebase master # rebase feature_branch onto latest master
-
これの図(で描かれている
https://asciiflow.com
を含む)。
最新の
または
最新
のコミットを上または右に配置します。
# Prior to rebase: feature_branch # received new commits while # master did too # # master # x # | feature_branch # x y # | | # x y # | / # git merge-base ────► x--y--y--y # master feature_branch | # x # # # After rebase: feature_branch has # been completely cherry-picked onto # the end of master # # feature_branch # y' # | # y' # / # y'--y'--y' # | # master x # | # x # | # x # | # x # | # x
-
"us"/"ours"。
=
HEAD
である。 上流ブランチ: 最初は最後のx
にコミットする。master
そして、その後、いくつかのNEWコミットが行われます。y'
,cherry-picked
そのうえで (これはやっかいだ!)。というのも、あなたが入力したときにgit rebase master
, git はまずmaster
のチェリーピックを開始する起点となります。feature_branch
にコミットしています。 のどのコミットかを決定し、そのコミットに対してfeature_branch
をチェリーピックする(つまり、あなたのfeature_branch
にないコミットはmaster
). これを行うにはmerge-base
(に共通するコミット)。feature_branch
とmaster
で見つけることができます。git merge-base master feature_branch
) からコミットを選び始めます。 の後に これmerge-base
の最後のコミットに向けて、一回一回作業していきます。feature_branch
の先端にあるmaster
これにより、すべての「新しい」ベースが作成されます。y
に追加したコミットをfeature_branch
を最新のmaster
として、新しいy'
がコミットします。したがって "us"/"ours"。 =HEAD
しかし、このリベースを行うために git が舞台裏で新しいチェックアウトを行ったため、このようになりました。HEAD
を入力したときにいたブランチではありません。git rebase master
. 代わりに 私たち またはHEAD
は、最後のx
にコミットする。master
の間に競合が発生した場合、最初のcherry-pick
または、NEWコミットであれば何でもよい。y'
へのチェリーピックに成功しました。master
は、それ以降のチェリーピック中に競合が発生した場合。 その はもう一方のコミットであり、これはあるy
からのコミットfeature_branch
に適用され、この新しいHEAD
を順番にチェリーピックして、最初のy
へのコミットfeature_branch
というのは、すぐに 後git merge-base master feature_branch
最後のy
にコミットする。feature_branch
. すぐ下にある "them" の説明も参照してください。 -
"them"/"theirs"
= ある
y
コミット元feature_branch
に適用され、新しくチェックアウトされたHEAD
で、ここでHEAD
は、最後のx
にコミットしています。master
をリベース中の最初のチェリーピック操作に使うか、あるいは新しく作成されたこれらのy'
の上にコミットしています。master
としてfeature_branch
がリベースされるか、あるいは一度に1つのコミットしか取得されない(新しいコミットの文字列に沿ってgit merge-base master feature_branch
の最後のコミットまでfeature_branch
) の上にmaster
. すぐ上の"us"の説明も参照。
-
サンプルコマンドです。
-
git revert
(ある意味直感的に)。-
サンプルコマンドです。
git checkout feature_branch # create a new commit to undo the changes from some_previous_commit # within feature_branch git revert some_previous_commit
- 今回の詳細な低レベルの仕組みについては、以下の下部にある「"結果と結論"」のセクションをご覧ください。 もう一つの回答はこちら と同様です。 torek さんの長くて詳しい回答はこちらです。 .
-
"us"/"ours"。
=
HEAD
である。feature_branch
ブランチにいたためfeature_branch
を実行した時にgit revert some_previous_commit
. より具体的には "us"/"ours" が表現する変更を含んでいます。git diff some_previous_commit..HEAD
これは、元に戻されたコミットから現在のコミットへの変更点です。 -
"them"/"theirs"
=(その逆)である。
some_previous_commit
の上に新しいコミットを作成し、その変更を元に戻す(undo)コミットです。feature_branch
). つまり "they"/"theirs"。 が表現する変更を含んでいます。git diff some_previous_commit..some_previous_commit~
ここでsome_previous_commit~
は 親コミット のsome_previous_commit
. これは、以下のことを意味します。 "them"/"theirs" は 反対 のsome_previous_commit
を元に戻すには、その変更の反対を含んでいるようにsome_previous_commit
を変更します。
-
サンプルコマンドです。
使用例です。
マージ競合の解決例。
# 1. Merge `feature_branch` into `master`, accepting ALL of
# `master`'s (`ours`) changes in the event of
# any merge conflicts!
git checkout master
git merge -X ours feature_branch
# 2. Merge `feature_branch` into `master`, accepting ALL of
# `feature_branch`'s (`theirs`) changes in the event of
# any merge conflicts!
git checkout master
git merge -X theirs feature_branch
以下は、その一部です。 私がよく使うテクニックを紹介します。 上記の2つの例ではなく
# 3. Assuming this merge attempt results in merge conflicts in
# these 3 files, but we know all of the changes on the `master`
# branch side are the ones we wish to keep, check out these 3
# files from `master` (`--ours`) to overwrite the conflicted
# files. Then, add these now-fixed files to stage them for
# committing, and continue (finish) the merge.
git checkout master
git merge feature_branch
git checkout --ours -- path/to/somefile1.c path/to/somefile2.c path/to/somefile3.c
git add path/to/somefile1.c path/to/somefile2.c path/to/somefile3.c
git status
git merge --continue
# 4. Assuming this merge attempt results in merge conflicts in
# these 3 files, but we know all of the changes on the `feature_branch`
# side are the ones we wish to keep, check out these 3
# files from `feature_branch` (`--theirs`) to overwrite the conflicted
# files. Then, add these now-fixed files to stage them for
# committing, and continue (finish) the merge.
git checkout master
git merge feature_branch
git checkout --theirs -- path/to/somefile1.c path/to/somefile2.c path/to/somefile3.c
git add path/to/somefile1.c path/to/somefile2.c path/to/somefile3.c
git status
git merge --continue
非常に便利な機能:もし
フォルダー全体
の競合が存在する場合、競合するすべての変更を受け入れるように指定することもできます。
--ours
または
--theirs
ブランチ
フォルダ全体を一度に
のような、このような!?
**最高のマージ競合の解決例:**。
# 5. [BEST EXAMPLE] Assuming this merge attempt results in merge conflicts in
# a bunch of files, some of which are inside `path/to/some/dir`, I can
# choose to accept the changes from one side or the other **for
# all conflicts within files inside this directory**, like this!:
git checkout master
git merge feature_branch
# Keep `--theirs` for all conflicts within files inside this dir
git checkout --theirs -- path/to/some/dir
# OR: keep `--ours` for all conflicts within files inside this dir
git checkout --ours -- path/to/some/dir
# Add (stage for committing) all changes within files inside this dir
# all at once
git add path/to/some/dir
git status
git merge --continue
ディーリング・ウィズ
path does not have our version
または
path does not have their version
ERRORS
もし、このようなことを実行することがあれば
git checkout --ours -- path/to/some/dir
...そして、うまくいかなかった! 何もしてくれないのです。代わりに、以下のようなエラーが出力されました。
error: path 'path/to/some/dir/file1.cpp' does not have our version error: path 'path/to/some/dir/file2.cpp' does not have our version error: path 'path/to/some/dir/file3.cpp' does not have our version
問題は、このエラーになったファイルが
削除
のファイルを
our
側で、そのため、我々は
git rm
を実行する前に、それぞれ手動で
git checkout --ours -- path/to/some/dir
.
git rm path/to/some/dir/file1.cpp path/to/some/dir/file2.cpp \
path/to/some/dir/file3.cpp
# then try again
git checkout --ours -- path/to/some/dir
また、代わりにこれを行うことで、処理を自動化することができます。
git checkout --ours -- path/to/some/dir \
|& gawk '{ print $3 }' | xargs git rm
git checkout --ours -- path/to/some/dir
上記のコマンドの詳しい説明は、こちらの回答をご覧ください。 git checkout --ours ファイル仕様に削除されたファイルが含まれる場合 .
警告 警告 警告!
以下に説明する問題のより詳細な例について。 他の回答はこちら .
をしないでください。
git checkout -- path/to/some/dir
また
git checkout some_branch -- path/to/some/dir
のような)競合解消の途中で
merge
をチェックアウトするつもりでなければ、上記の例のようなコンフリクトは起こりません。
すべて
からのファイル
HEAD
または
some_branch
で、それぞれディレクトリ
path/to/some/dir
そして、ローカルファイルをこれらのファイルで上書きし、それによって
ない
ただ
どちらか一方からの矛盾した変更を受け入れること。
言い換えれば 紛争解決中 、これです。
GOODです。
# GOOD :)
# Accept all conflicts from one side or the other (while still
# merging changes from both sides into one, in the event of being
# in the middle of a `git merge`).
git checkout --ours -- path/to/some/dir
# OR
git checkout --ours -- path/to/some/file
を受け付けます。
変更点のみ
側からの
--ours
というのは、常に安全で良いことなのですが、これに対して
BADです。
# BAD :(
# OVERWRITE all files with these files from `some_branch` instead,
# thereby _losing_ any changes and/or files contained in the other
# side but which are not in `some_branch`.
git checkout some_branch -- path/to/some/dir
# OR
git checkout some_branch -- path/to/some/file
は、完全に
チェックアウトして上書きする
ではなく、指定されたディレクトリまたはファイル全体が対象となります。
は、競合する変更そのものだけです。
このことは、以下のような完全なチェックアウトをすることで、不注意にどちらかの変更を削除してしまう可能性があることを意味します。
git checkout some_branch
でのコンフリクト解消ではなく
git checkout --ours
または
git checkout --theirs
.
を使用することが推奨されます。
git checkout --ours -- file_or_dir_paths
または
git checkout --theirs -- file_or_dir_paths
NOT
git checkout some_branch -- file_or_dir_paths
をするときはいつも
などは
git merge
,
git cherry-pick
,
git rebase
または
git revert
.
しかし、もしあなたが
git checkout some_branch -- file_or_dir_paths
この動作を理解した上で、それが
欲しい
ディレクトリ全体をチェックアウトしても、そのディレクトリに存在しないローカルファイルは
some_branch
ということです。その代わり、ローカルに存在し、かつ
some_branch
.
そのため、これらのファイルを手動ですべて削除する必要があります。
これを覚えておかないと、最終的に非常に困惑することになります。これについては、私の他の回答で詳しく説明しています。
こちら(この回答にも良い解決策があります)
そして
こちら
.
さらに進む/追加のメモとヒント。
-
上記のファイルの競合解消の例は、様々な種類の操作のいずれにおいても競合が発生した場合に適用できます(
git merge
,git cherry-pick
,git rebase
,git revert
など)を覚えておく必要がある以外はtheirs
とours
は、上記で説明したように、それぞれの紛争解決のための手段を意味する。 -
のようなブランチ名だけを使用することもできます。
master
またはfeature_branch
の代わりに-X ours
/-X theirs
と--ours
と--theirs
. 警告: ブランチ名を渡すのは簡単でわかりやすいように思えますが、この方法はあなたの変更にとって危険なものになりえます。 ファイル内のコンフリクトを解決するのではなく、ファイルやディレクトリを完全に置き換える。 . 上記の "WARNING WARNING" のセクションを参照してください。もしあなたが、どちらか一方からの競合する変更を受け入れるのではなく、完全なファイル置換を行いたいのであれば、以下の方法があります。# See "WARNING WARNING WARNING" section above. git checkout feature_branch -- path/to/somefile1.c path/to/somefile2.c path/to/somefile3.c
-
をチェックすることもできます。
ディレクトリ全体
ファイルを個別に指定するのではなく 参照
この回答はこちら
と
私の答えはこちら
そして
私のもう一つの答えはこちら
. 今テストしました。これも動作します。ただし、ここでも、上記の "WARNING WARNING" セクションに注意してください。これは、フォルダ全体に対して、どちらか一方からの競合する変更を受け入れるのではなく、ディレクトリ全体の置換を行うものです。
# Check out ALL files from feature_branch which are in # directory "path/to/dir". See "WARNING WARNING WARNING" # section above. git checkout feature_branch -- path/to/dir
-
を意図的に使用することを忘れないでください。
git checkout feature_branch -- path/to/dir
ディレクトリにあるローカルファイルを削除してくれることを期待する。path/to/dir
には存在しないがfeature_branch
の場合、それはできません。を実行する前に、または実行した後に、ローカルファイルシステムからそれらのファイルを手動で削除する必要があります。checkout
コマンドを使用します。詳しくはこちらの回答で。
参考文献
- [いつも参考にしている私の答えです!] "gitにおけるファイルやディレクトリのチェックアウトについてのすべて"。 別のブランチから 1 つのファイルだけを取得する方法
- [私の答え] なぜgitはパスによるハード/ソフトリセットを行えないのですか? --> 特に git の用語と定義 の中にある 背景知識"。 のセクションをご覧ください。
-
[私なりの答えですが、quot;they" と "us" は何を意味するのでしょうか?
git revert
] git revert` において `them` と `us` は誰ですか? -
[LeGEC さんの回答は、quot;ours/us" が常に
HEAD
そして "them/theirs" は常にもう一方のブランチまたはコミットです] 。 git revert` において `them` と `us` は誰ですか? -
[の理解について、既存の答えと照らし合わせてみました。
git merge
とgit rebase
] Git では、誰が "us" で、誰が "them" なのですか? -
から
man git checkout
: " git rebase や git pull --rebase の際に、私たちのものと彼らのものが入れ替わっているように見えることがあることに注意してください。 "。--ours, --theirs When checking out paths from the index, check out stage #2 (ours) or #3 (theirs) for unmerged paths. Note that during git rebase and git pull --rebase, ours and theirs may appear swapped; --ours gives the version from the branch the changes are rebased onto, while --theirs gives the version from the branch that holds your work that is being rebased. This is because rebase is used in a workflow that treats the history at the remote as the shared canonical one, and treats the work done on the branch you are rebasing as the third-party work to be integrated, and you are temporarily assuming the role of the keeper of the canonical history during the rebase. As the keeper of the canonical history, you need to view the history from the remote as ours (i.e. "our shared canonical history"), while what you did on your side branch as theirs (i.e. "one contributor’s work on top of it").
- [私の質問への回答]: ディレクトリのパスもgitに渡せば、ファイルを個別に指定する代わりに、ディレクトリ全体からすべてのファイルをチェックアウトすることができます。 特定のディレクトリのみについて、"their" ブランチからの git merge の競合を受け入れるにはどうすればよいですか?
- [私の答え]を git checkout --ours ファイル仕様に削除されたファイルが含まれる場合
- ASCIIのきれいな絵や図を描いて、コードの中に配置します。 https://asciiflow.com/ .
追加のスタディ
- [ この答えは、まだ自分で勉強する必要がありますね。 -done;私はそれを理解し、2020年1月7日現在、ここに私の答えを更新しました]。 git revert` において、`them` と `us` は誰ですか?
- (静流の声) これから勉強して 読まなきゃいけないのに git checkout --ours で、未マージファイル一覧からファイルが削除されない。
関連
-
[解決済み] Git で直近のローカルコミットを取り消すには?
-
[解決済み] Gitブランチをローカルやリモートで削除するには?
-
[解決済み] git pull」と「git fetch」の違いは何ですか?
-
[解決済み] コミット前に 'git add' を取り消すにはどうすればよいですか?
-
[解決済み] リモートのGitブランチをチェックアウトするには?
-
[解決済み] 新しいローカルブランチをリモートの Git リポジトリにプッシュし、それを追跡するにはどうすればよいのでしょうか?
-
[解決済み] Git リポジトリで削除されたファイルを検索して復元する方法
-
[解決済み] Gitブランチをmasterにマージする最も良い(そして最も安全な)方法は何ですか?
-
[解決済み】"git pull" でローカルファイルを強制的に上書きするには?
-
[解決済み】ローカルのGitブランチの名前を変更するには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Gitマージで「すでに最新」と報告されるが、違いはある
-
[解決済み] [Solved] 作業ツリーのディレクトリ 'example.com' を作成できませんでした。パーミッションが拒否されました
-
[解決済み】マージが終了していません(MERGE_HEADは存在します)。
-
[解決済み] 複数のコミットをチェリーピックする方法
-
[解決済み] GitBash | origin master - rejected (fetch first) | GitHub リポジトリにファイルがない。
-
[解決済み] gitの「ours」「theirs」の正確な意味を教えてください。
-
[解決済み】別のブランチから1つのファイルだけを取得する方法は?
-
[解決済み】ローカルのGitブランチをリモートの違う名前に簡単にプッシュするにはどうすればいいですか?
-
[解決済み] git rebase、'local' と 'remote' を追跡する
-
[解決済み] なぜgitはパスによるハード/ソフトリセットを行えないのですか?