2017-07-14 5 views
0

サブプロジェクトのマスターとしてmy_branchを作成しました(下図参照)。私は、サブプロジェクトとは無関係だったので、多くのファイルをmy_branchから削除しなければなりませんでしたが、これらのファイルはまだマスターに必要です。しばらくの間、masterとmy_branchの両方で開発が行われていました。Gitブランチをリベースまたはマージしても、削除されたファイルを保持する

サブプロジェクトが完了したので、my_branchからmasterに変更をリベースまたはマージします。しかし、私は、すべてのファイルをmy_branchで削除されたままにしたいが、まだmasterに存在している。これを行う最も簡単な方法は何ですか?

私はおそらく別のリポジトリを作成し、プロジェクトをリファクタリングするべきであることを認識しています。しかし、手元にある状況を考えれば、私は何ができますか、できれば手作業ではありませんか?

残念ながら、削除されたすべてのファイルが別々のコミットにあるとは限りません。あなたのmasterブランチから

* 172c3f3 (origin/my_branch, my_branch) comment 
| * e4f6849 (origin/master, origin/HEAD, master) Merge branch asdf 
| |\ 
| | * c796e73 aafg 
| |/ 
| * 75720e5 Merge branch zxcv 
| |\ 
| | * 7c694e9 changes 
| |/ 
* | 61370ac some 
* | 8afc0be development, 
* | d14263b bugfixes, 
* | 0d5a17f testing, 
* | 588cf8f maybe some cleanup 
* | 588cf8f here and there 
* | e1f990b and a lot of files 
* | 146212b removed 
* | 09c6278 but they are still needed in master 
|/ 
* 9a53a83 my_branch created here 
+0

マージベースのように、すべてのファイルのローカルコピーを取得し、ここで私の頭の上をオフに考えることから始めますmy_branch、次にマスターをコミットします。 my_branchをマスターにマージ(またはリベース)します。その後、すべてのファイルを再度追跡しますか? – jrahhali

答えて

1

UPDATE - リベース中にeditコミットを処理する方法の私の以前の説明が不正確であることに十分不明でした。明確化


(Benによって提案されたように)1つの作業可能なアプローチは、マージを編集することです。このマージがいくつかのコマンドによって行われた仮定(例えば、--preserve-mergesが指定されている場合でもrebase)に違反するという点で、潜在的な欠点があります。これにより、成功を報告している間に、そのようなコマンドが黙って壊れた結果を生成する原因となります。

さらに複雑ですが、代替手段があります。また、ブランチの履歴を書き直すことも含まれますが、ブランチをリベースすることができるので、問題はないと言いました。

ここでのアイデアは、ファイルの削除を履歴から破棄して、ブランチが作成されたときの状態でファイルが存在するようにすることです。 (正直に言うと、まず最初に何をすべきだったのでしょうか?)

これに最も適した手順は多くのことに依存します。より一般的には実行可能ですが、より複雑なものもあれば実行する方がはるかに単純なものもあります(ただし、特定のことが真である場合にのみ動作します)。

ファイルが一度にすべて削除されていないようで、他の変更が加えられた同じコミットで削除されたようです。

対話型のリベースが機能する可能性があります。確かにfilter-branchでそれを行うことができます。 2つの組み合わせによってはオプションになる場合もあります。

my_branchが線形であれば、ブランチ上でマージは行われません。対話型のリベースを使用している可能性があります。ポップアップ表示TODOリストで

git rebase --interactive master my_branch 

、任意のは、それが(代わりにデフォルトpickの)editため、不要な欠失を含む可能性がコミットマーク。リベースが進行すると、各パッチを暫定的にコミットした後に一時停止します。不要なあなたは

git diff --diff-filter D --no-renames --name-only HEAD^ 

ような何かを行うことができます削除見つけるには(よりシンプルなコマンドが動作します。これはあなたが逆転したいものを確認することができますので、削除されたファイル名のリストだけを取得しようとする具体的には、あなたがよく、または月。 --no-renamesは必要ありません;これは、誤って名前の変更が検出されても、削除が表示されないようにするためのものですが、実際に多くのファイルの名前を変更した場合、htemが削除される原因になります)。

具体的な削除

git checkout HEAD^ -- path/and/filename 

あなたが削除を持っている上記のリベースコマンドでも、masterの先端にあなたの仕事のリベースを完了します

git add . 
git commit --amend 

を逆転させました。 がない場合は、が必要です。あなたの代わりにmasterに仕事をマージしたい場合 - 作業からそれを続けるだろう複雑である場合には、マニュアルに思われる場合、あなたが

git rebase --interactive `git merge-base my_branch master` my_branch 

ような何かを行うことができ、または、あなたはfilter-branchを好むかもしれない - しかし、あること歴史が大きい場合、これは遅くなる可能性があると警告した。

この場合、削除されたファイルを再追加するのはtree-filterです。あなたが削除したマスターでuntrackすべてのファイルを - 私は

git checkout `git merge-base master my_branch` 
cp all/the/files/that/were/deleted some/path/where/I/can/find/them/later 

その後

git filter-branch --tree-filter 'cp some/path/where/I/can/find/them/later all/the/files/that/were/deleted' -- my_branch 
+0

ありがとう、マーク、これは教育的だった。私はマージを行うためにあなたのアプローチを使用することができました(私は感謝してそれをすべて必要としませんでした)。私は上記のベンの答えの部分も使っていました。 –

1

、マージを行うと--no-commitフラグを渡し:

git merge my_branch --no-commit

今、あなたは、マージ、削除したいファイルの未削除することができます。

git reset HEAD <file>

git checkout -- <file>

コマンドgit status表示されますそれはあなたがそう傾斜している場合、あなたは選択のチェックアウト/すべて削除されたファイル

をリセットするためにスクリプトでこの出力を解析し、最終的な結果をコミットするために進むことができ、削除したいファイル:

git commit

+0

それはいいと思う - 私は試して報告します。 –

+1

これは簡単なようで、うまくいくはずですが、必ずしもそれを推奨するとは限りません。その理由は、マージに遭遇した場合、さらなるリベースが混乱を招く可能性があるからです。マージが成功すると(しかし、望ましくない結果を生成する)、デフォルトの戦略を使用すると、 '--no-commit'を使ってマージを編集するのはやや危険です。とにかく、このレポのマージを元に戻すことはできません。すでに「悪いマージ」と呼ばれるものがあれば、それは問題ありません。そうでない場合は、私は別のアプローチ(別の回答として投稿します)を考えてみましょう –

+0

BenとMark:ありがとうございました。 –

関連する問題