しばらくの間、たまたま作業すべきでないブランチで作業をしていたので、適切な名前を付けてそこからブランチを作成しました。 今度は、本来作業すべきではなかったブランチを、オリジン(github)のバージョンに上書きしたいと思います。 これを簡単に行う方法はありますか? ブランチを削除してからトラッキングブランチをリセットしてみましたが、作業していたバージョンに戻ってしまいます。
まだoriginにプッシュしていない場合は、以下の方法で自分のブランチをupstreamブランチにリセットすることができます。
git checkout mybranch
git reset --hard origin/mybranch
(質問にあるように、最新のコミットを別のブランチで参照するようにしてください)
リセットした直後の mybranch@{1}
は、リセット前の古いコミットを参照していることに注意してください。
しかし、すでにプッシュしてしまっている場合は、 "Create git branch, and revert original to upstream state" を参照してください。
Git 2.23 (August 2019)では、それは1つのコマンドになります。git switch
となります。
すなわち、以下のようになります。git switch -C mybranch origin/mybranch
。
例
C:\Users\vonc\git\git>git switch -C master origin/master
Reset branch 'master'
Branch 'master' set up to track remote branch 'master' from 'origin'.
Your branch is up to date with 'origin/master'.
git reset --hard` のように、インデックスと作業ツリーを復元します。
Brad Herman]5によってコメントされているように、reset --hard
は、新しいファイルを削除するか、変更されたファイルをHEADにリセットする**でしょう。
実際には、リセット後に git clean -f -d
を行うことで、リセットしたばかりのブランチと 正確に 同じ作業ツリーを確保することができ、白紙の状態から始めることができます。
この blog post では、これらのエイリアスを提案しています(master
ブランチ専用ですが、あなたはこれらを適応/拡張することができます)。
[エイリアス] (英語) resetorigin = !git fetch origin && git reset --hard origin/master && git clean -f -d resetupstream = !git fetch upstream && git reset --hard upstream/master && git clean -f -d となります。 そして、次のように入力します。
git resetupstream を実行します。 とか と入力します。 git resetorigin
このようなことがあったとして
# on branch master
vi buggy.py # you edit file
git add buggy.py # stage file
git commit -m "Fix the bug" # commit
vi tests.py # edit another file but do not commit yet
そして、間違ったブランチで変更したことに気づく。
git checkout -b mybranch # you create the correct branch and switch to it
しかし、master
はまだあなたのコミットを指しています。以前に指していた場所を指すようにしたいのです。
一番簡単な方法は
git branch --force master origin/master
もうひとつの方法は
git checkout master
git reset --soft origin/master
git checkout mybranch
なお、reset --hard
を使用すると、コミットされていない変更が失われることに注意してください (私の例では tests.py
)。
私はサーバー上にプライベートリポジトリを持ち、定期的にリベース/フォースプッシュを行っているため、他のコンピュータ上のローカルブランチを頻繁にリセットする必要があります。そこで、次のようなエイリアスを作成しました: "catchup" これで現在のブランチに対してこれを行うことができます。他の回答とは異なり、このエイリアスにはハードコードされたブランチ名はありません。
ちょっと待ってください。
[alias]
catchup = "!f(){ echo -n \"reset \\033[0;33m$(git symbolic-ref -q --short HEAD)\\033[0m to \\033[0;33m$(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD))\\033[0m? (Y/n) \"; read -r ans; if [ \"$ans\" = \"y\" -o \"$ans\" = \"Y\" -o -z \"$ans\" ]; then git reset --hard $(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD)); else echo \"catchup aborted\"; fi }; f"
適切にフォーマットすると (.gitconfig の改行ではうまくいきません)、次のようになります。
"
!f(){
echo -n \"reset \\033[0;33m$(git symbolic-ref -q --short HEAD)\\033[0m to \\033[0;33m$(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD))\\033[0m? (Y/n) \";
read -r ans;
if [ \"$ans\" = \"y\" -o \"$ans\" = \"Y\" -o -z \"$ans\" ]; then
git reset --hard $(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD));
else
echo \"catchup aborted\";
fi
}; f
"
$(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD))
は現在のブランチの上流を表します。reset は潜在的に危険な呼び出しなので (特に --hard オプションをつけると、コミットされていない変更を失うことになります)、まず何をしようとしているのかを教えてくれます。例えば qcpp/dev-container というリモートの dev-container ブランチにいるときに、git catchup
と入力すると、次のようなプロンプトが表示されます。
reset dev-container to qcpp/dev-container?(Y/n)
yを入力するか、そのままリターンキーを押すと、リセットが実行されます。それ以外を入力すると、リセットは実行されません。
非常に安全に、ステージングされていない/コミットされていない変更の損失をプログラムで防ぎたい場合は、diff-indexのチェックに従うで上記のエイリアスをさらに強化することができます。
義務的な警告です。もしあなたが、他の人が作業のベースとしているパブリックリポジトリで作業していて、このエイリアスが必要なら、あなたは間違ったことをしています™。