以前gitで一度行った変更をなかったことにする方法4つを紹介しましたが、
日常的に git を使用していると他にも様々な
「なかったことにしたい」「元に戻したい」
という状況に遭遇します。
そのひとつひとつについて対処方法を紹介していきます。
詳細は gitで一度行った変更をなかったことにする方法4つ を参照してください。
$ git branch experimental
$ git checkout experimental
$ $EDITOR
$ git commit -am 'foo'
$ $EDITOR
$ git commit -am 'bar'
$ $EDITOR
$ git commit -am 'baz'
$ git checkout master
$ git branch -d experimentalそもそも実験的なことをするのであれば、
一度実験用のブランチ(例えば experimental)を作ってそこで作業し、
要らなくなったらそのブランチを削除(git branch -d)すれば済みます。
詳細は gitで一度行った変更をなかったことにする方法4つ を参照してください。
詳細は gitで一度行った変更をなかったことにする方法4つ を参照してください。
詳細は gitで一度行った変更をなかったことにする方法4つ を参照してください。
git の管理下にないファイルはgit clean
でまとめて削除することができます。
しかし「git の管理下にない」=「後から元に戻すことはできない」なのでgit clean は -f を指定しない限りファイルを削除しません。-n では削除対象のファイル名を表示するだけです。
実際の削除は慎重に確認をしたうえで行いましょう。
新しいファイルを git add したのであればこれでも同じ効果。
ただし、このコマンドの意味するところは「git リポジトリから $file を削除する」なので注意しましょう。
個々の変更箇所について元に戻すかそのままにしておくか選択することができます。
ただし git rebase 直後に git commit や git merge などのコマンドを実行していない時に限ります。
それも既にやってしまったという場合:git reflog
で各種操作が行われた時点のコミットが一覧できます。
適切なコミット(例えば abadcafe) を探してgit reset --hard abadcafe とすれば元に戻せます。
問題4や問題13と同様です。
実行後は適宜 git add と git commit をしましょう。
リリースブランチの更新作業が終わった後、
元のブランチで git stash pop すれば中断した作業を再開することができます。
例えば以下のような状況だったとします:
$ git checkout master
$ echo 'id=who' >conf
$ echo 'password=secret' >>conf
$ git add conf
$ git commit -m 'Add conf'
$ echo 'width=1024' >>conf
$ git commit -am 'Update conf 1'
$ echo 'height=768' >>conf
$ git commit -am 'Update conf 2'
$ echo 'color=256' >>conf
$ git commit -am 'Update conf 3'
$ git push origin master「本来 conf には生のパスワードを書いてはいけなかった」という状況です。
このとき、慌てて
$ sed -e '/^password=/d' conf >,conf
$ mv ,conf conf
$ git commit -am 'Remove the secret password'
$ git push origin masterなどとやっても、変更履歴を辿れば結局はパスワードを参照できてしまいます。
どちらのコマンドもかなりの荒業なので、周囲の状況をよく確認したうえで使いましょう。
git filter-branch
を使えば指定したコミットを自動で書き換えることが可能です。
今回の例の場合、 conf ファイル中のパスワード行をなかったことにしたいので、
以下のようなコマンドを実行します:
$ git filter-branch \
> --tree-filter 'sed -e "/^password=/d" <conf >,conf; mv ,conf conf' \
> master~4..master正しくファイルを書き換えることができたか確認し:
$ git log -p master~4..master -- conf問題なさそうなら公開リポジトリに push した内容を上書きしましょう:
$ git push origin master -fただし、このケースで行っていることは、既に公開した内容を自分の都合で上書きしていることに他ならず、
黙って行うと公開リポジトリを既に clone していた人達に大混乱を招くため、
必ず周囲の状況を確認して周知を徹底したうえで行いましょう。
(まあ、元のパスワードが恥ずかしいものだった場合は、やはり git filter-branch したくなりますが……)
(2011-09-02T18:06:54+09:00追加)
例えば以下のような状況だったとします:
$ git checkout master
$ git merge feature-x
Auto-merging SOMEFILE
CONFLICT (content): Merge conflict in SOMEFILE
Automatic merge failed; fix conflicts and then commit the result.
$ git diff | wc -l 12000
$ git diff | grep '<<<<<<<' | wc -l 8000マージに際してコンフリクトがあった場合、
作業ディレクトリにあるファイルはコンフリクト状況を示す<<<<<<< やら >>>>>>> やらのマーカーが埋め込まれた状態になります。
コンフリクトした箇所が10箇所くらいなら手作業でどうにかするところですが、
上記のように8000箇所くらい
(あるいはコンフリクトしたファイルが誠に遺憾ながら政治的な理由によりプレインテキストでない場合)
になるとさすがにそうも言ってられません。
手っ取り早く修正するにはファイルの内容をどちらか片方のブランチの最新版の内容で置き換えるのが一番なのですが、
どうすればよいでしょうか。
git checkout
を使います。通常、このコマンドはブランチの切り替えに使いますが、
ファイル名を指定すると作業ディレクトリ中の対応するファイルの内容を
特定のブランチでのファイルの内容で置き換えることができます。
例えば作業ディレクトリにある SOMEFILE ファイルの内容をmaster ブランチの内容で置き換えるには以下のコマンドでできます:
$ git checkout master -- SOMEFILE実際にはブランチだけでなく任意のコミットを指定することもできるので、
以下のようにして1前のコミットでの状態を取得することもできます:
$ git checkout HEAD~1 -- SOMEFILE実際にコンフリクトが発生した場合は
「どのブランチをどのブランチにマージしようとしていたか」
という情報が内部的に記録されているので、
直接ブランチ名を指定する代わりに以下のコマンドを使うこともできます:
$ git checkout --ours -- SOMEFILE--ours はマージ結果を取り込むブランチ(上記の例の場合 master)を表します。
現在のブランチのものから復元するため「ours」という訳です。
$ git checkout --theirs -- SOMEFILE--theirs はマージしようとしたブランチ(上記の例の場合 feature-x)を表します。
現在のブランチとは別のブランチのものから復元するため「theirs」という訳です。
(2012-07-02T14:33:15+09:00追加)
大抵の場合、一度は bar を git checkout しているはずです。
ならば git reflog HEAD で「 bar から別のブランチに git checkout した」ログが見つかるはずです。
そのログから $n の値を決めて git branch bar HEAD@{$n} を実行すれば復元できます。
一度も checkout してなかった場合は reflog にも記録されていないので調べようがありませんが、
この場合はそもそも bar で有益な作業をしていた訳ではないので、復元できなくとも問題ないはずです。
(2013-11-18T18:57:45+09:00追加)
本来なら
git checkout -b bar master
...
git push origin barとすべきところを
git checkout -b foo master
...
git push origin fooとやってしまいました。
ローカルのブランチは
git branch -m foo barでリネームできるので、これで
git push origin barとすれば本来のブランチ名で push はできます。
が、既に push してしまった foo についてはどうすれば無かったことにできるでしょうか。
(2015-05-14T18:49:58+09:00追加)
問題18の亜種ですね。