
インフラエンジニアの為のGit実践
Iacなどの利用のために、これまでGitの利用機会が少なかったインフラエンジニア向けの解説をインフラエンジニアの為のGit入門に記載しました。
該当記事では、ワーキングツリー、ステージングエリア(インデックス)、ローカルリポジトリといったGitを構成する概念と、それぞれのエリアのファイルシステム上でのデータの持ち方や動きを合わせて解説しました。
ここでは、試行錯誤しながらコーディングしつつ、自身や共同開発者が把握しやすいCommit履歴を残すために必要と思われるGit操作のキャンセルや削除について記載します。
3つのエリア内での後退処理
この章には、Gitの基本となる3つのエリア(ワーキングツリー、ステージングエリア、ローカルリポジトリ)において、変更を元に戻したり情報を削除する方法を記載します。
- ファイルを削除する`rm`(UNIXをベースOSの場合)や`git rm`
- ワーキングツリーでの変更を元に戻す`git restore`
- ワーキングツリーでの変更を一時保存する`git stash`
- ファイルをGit管理外にする`git rm –cached`
- Commitを取り消す`git reset`
について、それぞれ記載します。

ファイルを削除する
既にGitで管理されているファイルを単純に削除すると、Gitはファイルの削除を検知し、差分として扱います。
UNIXをベースOSにて、以下のようなコマンドを実行したり、WindowsのエクスプローラーやMacのfinderなどのGUI上からファイル削除することがここでの単純な削除に該当します。
$ rm ファイル名(またはファイルパス)
または、
$ rm -r ディレクトリ名(またはディレクトリパス)
Git管理されている`c.txt`を`rm`コマンドで削除すると、以下のような動きになります。
例
$ rm c.txt
$ git status
On branch main
Your branch is ahead of 'origin/main' by 1 commit.
(use "git push" to publish your local commits)
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: c.txt
no changes added to commit (use "git add" and/or "git commit -a")
ワーキングツリーから`c.txt`が削除されたことがgitに検知され、`c.txt`がステージングされていない旨(Changes not staged for commit)が表示されます。
$ git ls-files --stage
100644 53482ee7c67c9610a1de09170ec3a943ae9e3394 0 a.txt
100644 7c4a013e52c76442ab80ee5572399a30373600a2 0 b.txt
100644 72943a16fb2c8f38f9dde202b7a70ccc19c52f34 0 c.txt
ステージングエリア(インデックス)の状態を見ると、`c.txt`は存在していることになります。
ここで、`git add .`や`git add c.txt`を実行すると、ステージングエリアにも`c.txt`を削除したことが反映されます。
なお、ワーキングツリーからファイルを削除しつつ、ファイルを削除したことをステージングエリアに反映したい場合は、以下のように実行します。
$ git rm ファイル名など(ディレクトリ名やディレクトリパス付きも可)
例
$ git rm c.txt
$ git status
On branch main
Your branch is ahead of 'origin/main' by 1 commit.
(use "git push" to publish your local commits)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: c.txt
gitコマンドを使用せずに単純削除した場合と比べ、`c.txt`の削除がステージングエリアに伝わっています(Changes to be committed)
$ git cat-file -p 72943a16fb2c8f38f9dde202b7a70ccc19c52f34
aaa
なお、`c.txt`のオブジェクト情報は残っています。これは、`git reset`などを実行した際に、`c.txt`の情報が必要になる可能性があるための仕組みだと考えられます。
ワーキングツリーでの変更を元に戻す
まだ、`add`も`commit`もしていないワーキングツリーでの変更を元に戻す場合は、以下のように実行します。
$ git restore ファイル名など
例
$ cat c.txt
aaa
この状態からテキストエディタ等でファイルを編集します。
$ cat c.txt
aaa
bbb
例として、`bbb`という文字列を`c.txt`に追加しました。
$ git status
On branch main
Your branch is ahead of 'origin/main' by 5 commits.
(use "git push" to publish your local commits)
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: c.txt
no changes added to commit (use "git add" and/or "git commit -a")
gitは`c.txt`の変更を検知しましたが、変更内容はステージングエリアに反映されていない状態です。
$ git restore c.txt
`git restore`を実行し、`c.txt`のファイル内容を確認すると、編集する前の状態に戻っています。
$ cat c.txt
aaa
`c.txt`が編集される前の状態に戻り、ステージングエリアが認識している`c.txt`の状態と同じになったため、statusがcleenな状態であることが表示されます。
$ git status
On branch main
Your branch is ahead of 'origin/main' by 5 commits.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
ワーキングツリーでの変更を一時保存する
途中まで進めていた作業を中断し、別の作業をしたい場合や、2つのコードパターンの両方を交互にテストしたい場合に、`git stash`を用いることで、ワーキングツリーでの操作を一時保存し、commit時点の状態に戻すことができます。
`-k`オプションを用いると、既にgitで管理されているファイルを一時保存できます。
$ git stash -k

例
$ cat a.txt
aaaaa
bbbb
ccc
ddd
直前のcommitと一致した状態になっている`a.txt`に`eee`という文字列を追加します。
$ cat a.txt
aaaaa
bbbb
ccc
ddd
eee
$ git stash -k
`git stash`を実行後、以下のコマンドでstashした記録の一覧を確認できます。
$ git stash list
stash@{0}: WIP on main: faf31a5 19:08:41
stashしたので、`a.txt`がcommit時点の情報に戻りました。
$ cat a.txt
aaaaa
bbbb
ccc
ddd
`git stash show stash@{N}`や`git stash show -p stash@{N}`コマンドを実行すると、一時保存されたファイルの一覧や差分を確認できます。なお、`-u`オプションでstashしても、stash前にUntracked files扱いになっていたファイルは表示されません。`N`には`git stash list`で確認した`{N}`の値を入力します。
他の作業やCommitを実施後、
$ git stash pop
または、
$ git stash pop stash@{N}
コマンドにて、一時保存した内容をワーキングツリーに戻すことができます。なお、`pop`の部分を`apply`に置き換えると、stashした内容を残したまま、復元が可能です。2種類のコードを交互にテストしたい時などは`apply`を用いると良さそうです。
ファイルをGit管理外にする
ファイルを削除するために`git rm`を実行すると、ファイルがワーキングツリーから削除もされますが、ファイルをワーキングツリーに残しつつGitの管理から外したいケースも考えられます。例えば、リモートリポジトリにpushするとセキュリティリスクが高まるCredentialファイルや、開発中に生成される一時ファイルなどがそれに該当します。
それらのファイルがGit管理になっていると気づいた場合、以下のコマンドを実行することで、ファイルをワーキングツリーに残しつつGit管理対象から外すことができます。なお、ワーキングツリーに存在するファイルを永続的にGit管理外とするためには、`.gitignore`に該当のファイル名などを記載することが必要です。
$ git rm --cached ファイル名など
Git管理されている`c.txt`を`git rm –cached`コマンドで削除すると、以下のような動きになります。
例
$ git rm --cached c.txt
$ git status
On branch main
Your branch is ahead of 'origin/main' by 1 commit.
(use "git push" to publish your local commits)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: c.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
c.txt
`git rm –cached`コマンドを実行すると、上記のように`c.txt`がステージングエリア(インデックス)から削除されたことになります。同時に、`c.txt`はgit管理外(Untracked)になったことが分かります。
この後にCommitすると、`c.txt`が削除された状態のCommitが作成されます。
例
$ git commit -m test_commit_2
$ git status
On branch main
Your branch is ahead of 'origin/main' by 2 commits.
(use "git push" to publish your local commits)
Untracked files:
(use "git add <file>..." to include in what will be committed)
c.txt
nothing added to commit but untracked files present (use "git add" to track)
`c.txt`を削除するCommitを作成したので、`c.txt`を削除することがCommit予定のリストから消えます。ワーキングツリーからは、`c.txt`を削除していないので、git管理外という表示は変わりません。`.gitignore`に`c.txt`と記載することで、`c.txt`は`Untracked files`のリストに表示されなくなります。
Commitを取り消す
誤ってCommitしてしまった場合や、既存のCommit内容に変更を加えたい場合、以下のように実行することで、Commit履歴をさかのぼることができます。
$ git reset --soft 戻したいポイント
最新のCommitであるCommitID`abcdef1234567890….`を取り消す場合の例を示します。
例
$ git log
commit abcdef1234567890.... (HEAD -> main)
Author: Name <name@example.com>
Date: Tue Jan 21 19:49:58 2025 +0900
test_commit_2
commit 1234567890abcdef.... (HEAD -> main)
Author: Name <name@example.com>
Date: Tue Jan 21 18:30:23 2025 +0900
test_commit_1
$ git reset --soft HEAD^
`HEAD^`は直前のコミットを指します。`HEAD^`ではなく、取り消したいCommitIDである`abcdef1234567890….`も指定できます。
$ git log
commit 1234567890abcdef.... (HEAD -> main)
Author: Name <name@example.com>
Date: Tue Jan 21 18:30:23 2025 +0900
test_commit_1
`git log`の結果から、CommitID`abcdef1234567890….`のCommitが表示が消え、CommitID`1234567890abcdef….`が最新のCommitとして表示されています。
Commitの取り消しと同時に、ワーキングツリーを取り消し後の最新Commitと一致した状態にしたい場合は`–hard`オプションを使用します。`–hard`オプションでの`reset`は、ワーキングツリーの状態を一気に戻したい場合に有用です。
例
$ git reset --hard HEAD^
ブランチに関する後退処理
この章には、ブランチを削除する方法として、
- ローカルブランチを削除する`git branch -d`
- リモートリポジトリに存在しないリモート追跡ブランチを一括削除する`git fetch –prune`
について、それぞれ記載します。
ローカルブランチを削除する
ローカルブランチを削除する場合、以下のように実行します。
$ git branch -d ブランチ名
`test`というローカルブランチを削除する例を示します。
例
$ git branch -a
* main
test
remotes/origin/main
remotes/origin/test
削除前には、ブランチ一覧に`test`ブランチが存在しています。
$ git branch -d test
Deleted branch test (was 123456ab).
`git branch -d`コマンドによって、`test`ブランチを削除しました。
$ git branch -a
* main
remotes/origin/main
remotes/origin/test
`test`ブランチが削除されたことを確認できました。
この時、Gitの内部的には`.git/logs/refs/heads/test`や`.git/refs/heads/test`という削除したブランチに関するファイルが削除されます。
また、`git log`コマンドで確認すると、削除した`test`ブランチの現在地を示す情報(ポインタ)が消えています。
削除前
$ git log
(略)
commit 987654321fedcba.... (origin/test, test)
Author: Name <name@example.com>
Date: Sun Oct 27 09:56:47 2024 +0900
test_commit_0
(略)
削除後
$ git log
(略)
commit 987654321fedcba.... (origin/test)
Author: Name <name@example.com>
Date: Sun Oct 27 09:56:47 2024 +0900
test_commit_0
(略)
リモートリポジトリに存在しないリモート追跡ブランチを一括削除する
リモートブランチにマージしたリクエストのブランチを自動削除する機能があったり、マージした後にマージ元のブランチを削除する運用がある時に、リモートで削除されたブランチに対応するリモート追跡ブランチは不要です。
リモート追跡ブランチとは、以下のうち`remotes/origin/xxxx`のようなブランチを指します。
例
$ git branch -a
main
test2
* test3
remotes/origin/main
remotes/origin/test
remotes/origin/test2
remotes/origin/test3
リモートリポジトリに存在しないリモート追跡ブランチを一括削除するには、以下のコマンドを実行します。
$ git fetch --prune

図のように、`test2`および`test3`というブランチがリモートリポジトリに存在しない場合、`git fetch –prune`を実行することで、以下のように`test2`および`test3`に対応するリモート追跡ブランチ`remotes/origin/test2`および`remotes/origin/test3`が消えます。
$ git branch -a
main
test2
* test3
remotes/origin/main
remotes/origin/test
Mergeに関する後退処理
この章には、Mergeを取り消す方法として、
- Commit履歴のみMerge前の状態に戻す`git reset –soft`
- ワーキングツリーもMerge前の状態に戻す`git reset –hard`
- Mergeの履歴を残してMerge前の状態に戻す`git revert`
について、それぞれ記載します。
Mergeの実態はCommitであるため、Commitの取り消しと同じコマンドを実行しますが、`git revert`のみ、Mergeに特化した取り消しコマンドとなっています。
Commit履歴のみMerge前の状態に戻す
Mergeを取り消すには、Commitの取り消しに用いるコマンドと同じものを使用します。Commitの取り消し時もそうであったように、`–soft`オプションを使用する場合は、履歴だけ取り消され、ワーキングツリーの状態は取り消し前と変わりません。
$ git reset --soft 戻したいポイント
以下に、マージコミットを取り消す例を示します。

例
$ git merge main
`test`ブランチにて、`main`ブランチをMergeし、CommitID`ababab0101010101….`が取り込まれたとします。
$ git log
commit cdcdcd2323232323.... (HEAD -> test)
Merge: efefef5 ababab0
Author: Name <name@example.com>
Date: Fri Jan 24 20:13:58 2025 +0900
Merge branch 'main' into test
commit ababab0101010101.... (main)
Author: Name <name@example.com>
Date: Fri Jan 24 19:57:50 2025 +0900
test_commit_5
commit efefef5656565656....
Author: Name <name@example.com>
Date: Fri Jan 24 09:57:48 2025 +0900
test_commit_4
ログに`main`ブランチのポインタ(現在地)や`main`ブランチをMergeした際のCommit情報が記録されています。
以下のコマンドを実行して、履歴を直前のCommit(Merge前のCommit)に戻します。
$ git reset --soft HEAD^
$ git log
commit efefef5656565656.... (HEAD -> test)
Author: Name <name@example.com>
Date: Fri Jan 24 09:57:48 2025 +0900
test_commit_4
`HEAD`が、MergeしてCommitID`ababab0101010101….`が取り込まれる前のCommitに戻りました。`main`ブランチのポインタや`main`ブランチでのCommitであるCommitID`ababab0101010101….`の情報が履歴に表示されていません。
$ git status
On branch test
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: b.txt
なお、`–soft`オプションを用いて`reset`をしたので、Mergeして取り込んだ差分がステージングエリアおよびワーキングツリーに残った状態になります。
このままCommitするか、何かの操作をした後に`add`および`commit`することで、MergeしたCommit履歴を残さず、Merge元の情報を取り込んだ状態(または、さらに変更を加えた状態)のCommitを生成できます。
ワーキングツリーもMerge前の状態に戻す
履歴だけでなく、ワーキングツリーもMerge前の状態に戻す場合は、`–hard`オプションを使用します。
$ git reset --hard 戻したいポイント

例
$ cat d.txt
aaa
Merge前の`d.txt`には`aaa`という文字列のみ格納されていたとします。
$ git merge main
上記のコマンドを実行して、`main`ブランチをMergeしました。
$ git log
commit 12341234abcdabcd.... (HEAD -> test)
Merge: 9876987 4321432
Author: Name <name@example.com>
Date: Fri Jan 24 22:24:30 2025 +0900
Merge branch 'main' into test
commit 43214321dcbadcba.... (main)
Author: Name <name@example.com>
Date: Fri Jan 24 22:21:50 2025 +0900
test_commit_8
commit 98769876fedcfedc....
Author: Name <name@example.com>
Date: Fri Jan 24 22:13:20 2025 +0900
test_commit_7
ログに`main`ブランチのポインタ(現在地)や`main`ブランチをMergeした際のCommit情報が記録されています。
`main`ブランチとの差分が反映されました。
$ cat d.txt
aaa
bbb
以下のコマンドを実行して、直前のCommit(Merge前のCommit)に戻します。
$ git reset --hard HEAD^
`HEAD`が、MergeしてCommitID`43214321dcbadcba….`が取り込まれる前のCommitに戻りました。`main`ブランチのポインタや`main`ブランチでのCommitであるCommitID`43214321dcbadcba….`の情報が履歴に表示されていません。
$ git log
commit 98769876fedcfedc....
Author: Name <name@example.com>
Date: Fri Jan 24 22:13:20 2025 +0900
test_commit_7
`–hard`オプションを用いて`reset`をしたので、Mergeして取り込まれた変更はワーキングツリーからも取り消されます。
$ cat d.txt
aaa
最新Commitとワーキングツリーの状態が一致しているので、ステージングエリアはcleanな状態となっています。
$ git status
On branch test
nothing to commit, working tree clean
Mergeの履歴を残してMerge前の状態に戻す
Mergeした履歴を残しつつ、Merge前の状態に戻す場合、以下のように実行します。
$ git revert -m 1 マージコミットのID
`git revert`コマンドを用いたMergeの取り消しは、以下のような動きになります。

例
$ cat d.txt
aaa
bbb
Merge前の`d.txt`には`aaa bbb`という文字列が格納されています。
$ git merge main
`test`ブランチにて、`main`ブランチをMergeし、CommitID`171717aeaeaeae….`が取り込まれたとします。
$ git log --graph
* commit 979797fdfdfdfd.... (HEAD -> test)
|\ Merge: 313131c 171717a
| | Author: Name <name@example.com>
| | Date: Sat Jan 25 07:50:18 2025 +0900
| |
| | Merge branch 'main' into test
| |
| * commit 171717aeaeaeae.... (main)
| | Author: Name <name@example.com>
| | Date: Sat Jan 25 07:48:08 2025 +0900
| |
| | test_commit_10
| |
* | commit 313131cacacaca....
| | Author: Name <name@example.com>
| | Date: Sat Jan 25 07:45:30 2025 +0900
| |
| | test_commit_9
| |
`main`ブランチとの差分が反映されました。
$ cat d.txt
aaa
bbb
ccc
以下のコマンドで、Mergeした履歴は残しつつ、ワーキングツリーをMerge前の状態に戻します。
$ git revert -m 1 979797fdfdfdfd
[test eeff781] Revert "Merge branch 'main' into test"
1 file changed, 1 deletion(-)
MergeしたCommitの先に、`revert`のCommitが追加されました。
$ git log --graph
* commit eeffaa77991122.... (HEAD -> test)
| Author: Name <name@example.com>
| Date: Sat Jan 25 12:47:01 2025 +0900
|
| Revert "Merge branch 'main' into test"
|
| This reverts commit 979797fdfdfdfd...., reversing
| changes made to 313131cacacaca.....
|
* commit 979797fdfdfdfd.... (HEAD -> test)
|\ Merge: 313131c 171717a
| | Author: Name <name@example.com>
| | Date: Sat Jan 25 07:50:18 2025 +0900
| |
| | Merge branch 'main' into test
| |
| * commit 171717aeaeaeae.... (main)
| | Author: Name <name@example.com>
| | Date: Sat Jan 25 07:48:08 2025 +0900
| |
| | test_commit_10
| |
* | commit 313131cacacaca....
| | Author: Name <name@example.com>
| | Date: Sat Jan 25 07:45:30 2025 +0900
| |
| | test_commit_9
| |
ワーキングツリーは、Merge前の状態に戻っています。
$ cat d.txt
aaa
bbb
`revert`コマンドの`-m 1`という指定は、マージコミットの`Merge: 313131c 171717a`左側のCommitIDに戻すという意味です。`-m 2`と指定すると、ワーキングツリーはCommitID`171717aeaeaeae….`の状態になります。
$ cat d.txt
aaa
bbb
ccc
`test`ブランチにMergeした`main`ブランチの最新Commit`171717aeaeaeae….`には、`d.txt`に`ccc`という文字列が含まれる状態であったため、`-m 2`を指定して`171717aeaeaeae….`側のCommitIDの状態に`revert`したことにより、`d.txt`には`ccc`という文字列が含まれたままになります。
ログを確認すると、`171717aeaeaeae….`に加えられた変更(マージコミット`979797fdfdfdfd….`を指す)を元に戻す旨がコミットメッセージに記載されています。
`-m 1`を指定して`revert`したときのコミットメッセージは、`This reverts commit 979797fdfdfdfd…., reversing changes made to 313131cacacaca…..`でした。
$ git log --graph
* commit 131313acacacac.... (HEAD -> test)
| Author: Name <name@example.com>
| Date: Sat Jan 25 13:46:43 2025 +0900
|
| Revert "Merge branch 'main' into test"
|
| This reverts commit 979797fdfdfdfd...., reversing
| changes made to 171717aeaeaeae.....
|
* commit 979797fdfdfdfd.... (HEAD -> test)
|\ Merge: 313131c 171717a
| | Author: Name <name@example.com>
| | Date: Sat Jan 25 07:50:18 2025 +0900
| |
| | Merge branch 'main' into test
| |
| * commit 171717aeaeaeae.... (main)
| | Author: Name <name@example.com>
| | Date: Sat Jan 25 07:48:08 2025 +0900
| |
| | test_commit_10
| |
* | commit 313131cacacaca....
| | Author: Name <name@example.com>
| | Date: Sat Jan 25 07:45:30 2025 +0900
| |
| | test_commit_9
| |
リモートリポジトリでの後退処理
この章には、リモートリポジトリでの後退処理として、
- 推奨されないpush情報の削除操作
- リモートリポジトリのブランチ削除
- リモートリポジトリでのMergeの取り消し
について、それぞれ記載します。
ローカル環境のように、複数の方法を使い分けたり、複雑な操作によってCommitや履歴を変更することはあまりなさそうです。リモートリポジトリは共同開発するリポジトリのマスター情報であるが故に、データや履歴情報の損失が起きづらくなるようなルールや仕様としているのかもしれません。
推奨されないpush情報の削除操作
リモートリポジトリのブランチの状態の方が新しい状態のとき、ローカルリポジトリのブランチをリモートリポジトリに`push`すると、エラーが出て処理を完了できません。
その場合、`-f`オプションを付けることで、強制的に`push`できますが、この操作は推奨されません。
$ git push -f origin ブランチ名
$ git log --graph
* commit 515151dadadada.... (HEAD -> test)
| Author: Name <name@example.com>
| Date: Sat Jan 25 14:21:05 2025 +0900
|
| commit_test_12
|
* commit 1e1e1ea7a7a7a7...
| Author: Name <name@example.com>
| Date: Sat Jan 25 12:58:35 2025 +0900
|
| commit_test_11
|
最新のCommitIDが`515151dadadada….`の状態で、リモートリポジトリに`push`します。
$ git push origin test
Enumerating objects: 48, done.
Counting objects: 100% (48/48), done.
Delta compression using up to 8 threads
Compressing objects: 100% (35/35), done.
Writing objects: 100% (45/45), 4.39 KiB | 2.20 MiB/s, done.
Total 45 (delta 14), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (14/14), done.
To github.com:example/git_test.git
44c21df..515151d test -> test
`push`した情報が、リモートリポジトリに反映されました。

ここで、ローカルリポジトリにて、Commitをキャンセルします。
$ git reset --hard HEAD^
HEAD is now at 1e1e1ea 12:58:35 test
Commit`515151dadadada….`がキャンセルされ、`HEAD`は`1e1e1ea7a7a7a7….`となりました。
$ git log --graph
* commit 1e1e1ea7a7a7a7 (HEAD -> test)
| Author: Name <name@example.com>
| Date: Sat Jan 25 12:58:35 2025 +0900
|
| commit_test_11
|
この状態でリモートリポジトリに`push`すると、ローカルリポジトリのブランチのtip(先端)がリモートリポジトリの対応するブランチより遅れていることを指摘され、処理されません。
$ git push origin test
To github.com:example/git_test.git
! [rejected] test -> test (non-fast-forward)
error: failed to push some refs to 'github.com:example/git_test.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push
以下のように、`-f`オプションを付けることで、リモートリポジトリに反映できますが、この操作は推奨されません。
$ git push -f origin test
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:example/git_test.git
+ 515151d...1e1e1ea test -> test (forced update)
リモートリポジトリもCommitID`1e1e1ea7a7a7a7….`が最新の状態となりました。

このように、リモートリポジトリの状態を戻すことができますが、リモートリポジトリは共同開発するリポジトリのマスター情報であるため、強制的な変更をすることは推奨されません。仮に非常に古い状態のローカルリポジトリの情報を`-f`オプション付きで`push`してしまい、他の共同開発者もローカルリポジトリに新しいCommit情報を保持していない場合、失われたコードや履歴を元に戻すことができなくなります。
リモートリポジトリのブランチ削除
リモートリポジトリに不要なブランチがたまると、ブランチ一覧やブランチ選択画面から必要なブランチを探しづらくなどの弊害が出てきます。
手動で削除したり、Git管理サービスの機能を用いて自動削除するなどの対応をお勧めします。
GitHubの場合、ブランチ一覧の画面から削除できます。

リモートリポジトリでのMergeの取り消し
リモートリポジトリ上のマージコミットを取り消すために、多くのGit管理サービスでは、マージコミットをrevertする機能を備えているようです。
ローカル環境でマージコミットを打ち消すCommitを作成し、リポートリポジトリにpushできますが、GitHubなどのGit管理サービス上で操作する方が少ない操作で目的を果たすことができます。
以下に、GitHub上でマージコミットをキャンセルする操作の例を示します。ここでは、pull request #6によるMerge処理をキャンセルすることとします。

Mergeしたことをキャンセルしたいpull requestを開き、Revertボタンを押します。Revert用のpull request作成画面が開くので、必要に応じて説明などを記入し、Create pull requestボタンを押します。

作成されたpull requestのファイル差分は、キャンセルしたいマージコミットを打ち消す内容になっています。

作成されたpull requestをMergeすると、Commitが生成され、リモートリポジトリ上でのMergeのキャンセル処理が完了します。

まとめ
ここまで、Git操作のキャンセルや削除について記載しました。スムーズにコードを管理する参考になれば幸いです。