2013-07-25 22 views
9

私はちょうど好奇心からこれを求めています。実際の状況でこのような状況に対処する他の方法がありますが、私はgitの以下の動作が少し奇妙なことがわかります。stashからのRebasing、奇妙な結果

要約:Stashingは、カーテンの後ろに2つのコミットを作成します.1つはインデックスを含み、もう1つは追加されない編集を含みます。後者をチェックアウトしてリベースしようとすると、何らかの形でインデックスからの変更だけが得られます。何故ですか?

詳細な例は、次のとおりです。

まず、インデックスに追加されたもう一つの編集、インデックスに追加されていない、その後1本のより、編集、および隠し、1コミットでのレポを作成してみましょう:

git init 
echo 1 > a.txt 
git add a.txt 
git commit -m"First commit" 
echo 2 >> a.txt 
git add a.txt 
echo 3 >> a.txt 
git stash 
git log --all --graph --oneline 

    * 5c00fc0 WIP on master: c8af537 First commit 
    |\ 
    | * 965c986 index on master: c8af537 First commit 
    |/ 
    * c8af537 First commit 

だから、git stashは、自分のハッシュ(私の場合は、インデックスの場合は965c986、非追加の編集の場合は5c00fc0)を使用して、インデックスと追加されていない編集をコミットとして保存するようです。

今すぐ新しいファイルを編集し、コミット:

echo x >> b.txt 
git add b.txt 
git commit -m"Second commit" 

ので、コミットのすべてが今のように見える:

git log --all --graph --oneline 

    * b589f50 Second commit 
    | * 5c00fc0 WIP on master: c8af537 First commit 
    | |\ 
    |// 
    | * 965c986 index on master: c8af537 First commit 
    |/ 
    * c8af537 First commit 

言って、私たちは今、隠し編集を取り、それらを組み合わせたいです2回目のコミット。今

git checkout 5c00fc0 
[warning message here] 
cat a.txt 
    1 
    2 
    3 
git rebase master 
    First, rewinding head to replay your work on top of it... 
    Applying: index on master: c8af537 First commit 

しかし、結果のファイル:この(git stash applyをのような、しかし、我々はすでに、その後スタッシュを洗浄し、いた場合REFLOGからコミット掘っ何)が、ちょうどで試してみましょうを行うには、他の方法があります。 a.txtだけです:

cat a.txt 
    1 
    2 

これは全体のグラフである:

git log --all --graph --oneline 
    * 5fc3ade index on master: c8af537 First commit 
    * b589f50 Second commit 
    | * 5c00fc0 WIP on master: c8af537 First commit 
    | |\ 
    |// 
    | * 965c986 index on master: c8af537 First commit 
    |/ 
    * c8af537 First commit 

だから、リベースだけAP、我々は5c00fc0をコミットチェックアウトしていても、のように見えますコミット965c986からの変更、つまり、私たちが隠していたときのインデックスにあった編集を加えました。しかし、5c00fc0にあったものは無視されました。

質問:なぜですか?この行動のいくつかの合理的な説明がありますか?またはこれはバグと見なされるべきですか?

答えて

1

git(デフォルト)では、リベース時にマージコミットが無視されます。 stashingはWIPコミットとインデックスコミットを作成し、WIPコミットはインデックスコミットとc8af537の両方を親として持つため、マージです。

そのように隠すこととは関係ありません。

+0

これはインデックスのコミットを無視する理由を説明していません。リベースは通常、マージコミットを削除しますが、マージされたコードが削除されるわけではありません。 – Ilion

+0

インデックスコミットを無視しません。 –

-1

私の元の答えに大規模な編集。

私はコードにいくつかのダイビングを行い、自分のテストをいくつか行い、問題を発見しました。あなたがあなたのヘッドレス支店にあなたのリベースをするとき、あなたはマスターを退治します。 rebaseコマンドは、リベースしているブランチのヘッドを検証します。この場合、スティッシュは含まれません。代わりにこれを試してみてください:

git checkout -b stashbranch 5c00fc0 
git rebase stashbranch 
git log --oneline --decorate --all 

次のようなものが表示されるはずです。

b589f50 (HEAD, refs/stash, stashbranch) Second commit 

注:デタッチヘッド状態にあるが、git rebase masterを実行した場合、それは、私のテストによると、に頭を設定しますがマスターヘッド。 git rebase 5c00fc0を実行して、ブランチングで行ったのと同じ結果が得られました。

+0

あなたが理解できなかったように見えますが(上記)、コミット5c00fc0と965c986はstashコマンドで作成されています。 –

+0

私はそれを理解しています。 stashコマンドの通常の動作を回避しようとしています。 – Ilion

+0

はい、上記のケースはおそらく乱用されているか、少なくともそれほど通常の使用ではありません。しかし、私は '5c00fc0'をリベースしようとすると、' 5c00fc0'は**リベースされていませんが、 '965c986'は直感的ではありません。これはどの意味で保護的ですか?私が '965c986'を再構築したければ、' 965c986'からrebaseすることができませんでした。 –

0

GUIアプリケーションで偶然に隠しを落とした後、今朝この問題を横断しました。最初は、他の人が行ったようにリベースを試みました。それは自然なことですから。それから、私はduckduckgoを使ってこれを検索して見つけましたが、実際の解決策はありませんでした。だから私は少し難しくしようと、この思い付いた:希望 コンテンツ

  • parentOfStashにコミット人工マージを指し

    • droppedStash:私たちは、次の枝/レフリーを持っていると仮定すると

      元の基点を指す 旧ステッチブランチ

    Th我々は、単に行うことができますエン:

    1. GitチェックアウトparentOfStash
    2. gitの桜-選ぶ-m 1 droppedStash

    -m 1祖先の1つは、メインラインであることを考慮するのgitに指示します。タダ!お気軽に:-)