0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

VSCodeの「同期」ボタンの裏側で何が起きているのか確認した

Last updated at Posted at 2025-04-15

はじめに

これまで、VSCodeの「同期」ボタンを、何気なく使っていました。
どのようなGitコマンドが実行されているか理解できていなかったため、調べた結果を記録します。

VSCodeで「同期」を実行すると何が起きているのか?

Gitログの確認方法

VSCodeのターミナルから「出力」タブを開き、「Git」でフィルターをかけます。
image.png

「同期」ボタンを押しただけでも、大量のログが Info レベルで出力されることが分かります。
ここでは、関連する Pull / Push のログのみを抜粋します。

Gitログ
2025-04-15 18:52:47.796 [info] > git pull --tags origin master [5312ms]
2025-03-28 18:52:47.796 [info] From https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/test-repo
 * branch            master     -> FETCH_HEAD
~中略~
2025-03-28 18:52:54.083 [info] > git push origin master:master [6276ms]
2025-03-28 18:52:54.084 [info] remote: Validating objects: 0%        
remote: Validating objects: 100%        
To https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/test-repo
   2e8677d..8a08c6a  master -> master

実行されているGitコマンドの内容

git pull --tags origin master

リモート origin/master の更新を取得し、ローカルに取り込み(既定挙動はmerge)

git push origin master:master

ローカルのmasterをリモートに反映

解説

VSCode の「同期」ボタンは、内部的に git pull → git push を順に実行していることが分かりました。

この機能は、リモートの変更を先に取り込み、自分の変更を反映したい場面では便利です。
先にリモートの変更を取り込むため、安全でだとも考えられるでしょう。

しかし、リモートとローカルが分岐していると pull が merge を行い、マージコミットが1つ生成され、履歴が見づらくなります。

たとえば、リモートとローカルの作業が分岐していた場合、以下のようにマージコミットが作成されます。

・リポジトリの状態:

A──B (origin/main)
└─C─D (ローカル)

・git pull(= fetch + merge)の結果:

A──B────────M
└─C─D───┘
↑ マージコミット(M)

マージコミットとは

2つ以上の親コミットを持つ特別なコミット
分岐した2本の履歴を一つにまとめた接合点となる

意図しないマージコミットを作らないために

マージコミットは必要か?

二つのブランチを統合する場合など、マージコミットが適切な場合はあります。
しかし、VSCodeの「同期」ボタンの既定挙動を理解しないばかりに、意図しないマージコミットを作成するのは避けたいですね。

以下に、解決方法を記載します。

VSCodeのGUI操作:「プル - リベース」→「プッシュ」ボタン

VSCode の 「プル(リベース)」 ボタンで変更を取り込み、次に「プッシュ」します。
Gitコマンド:git pull --rebase

リベースは、自分のコミットを最新の先端に付け替える操作です。

上記の分岐例でリベースをすると、ローカルの C, D は付け替えられて C', D' になり、履歴は一直線になります。

A──B──C'──D'

リベースの注意点(重要!)

リベースは名前の通り、コミットIDを付け替えます。
そのため、すでに他人が参照している(Push済みの)履歴を付け替えるのは、原則NGです。
他のユーザが取得しているコミットIDとズレが生じ、可能性があります。

OKなケースは、ローカルにしかない(未pushの)自分のコミットを更新したい場合のみです。

たとえば、以下はOKな例です。

リモート: A──B
ローカル: A──B──c──d (未push)

そこで、リベースをしても、コミットIDが変わるのはローカルのみです。

rebase後: A──B──c'──d' (ローカルのみID変わる)

一方で、以下はNGな例です。
自分がC─D を push 済みのあと、rebase して C'─D' にした場合:

origin/feature: A──B──C──D
ローカル: A──B──C──D (ここでrebase)
rebase後ローカル: A──B──C'──D' ← 旧C,Dとは別物

リベース後、プッシュするには --force が必要となります。
もし、--force で上書きした場合、他の人のローカルには 古い C,D が残ります。
その場合、pullでは直らず、git fetch ののちrebaseし直す or reset し直すなどの対応を強いられます。

VSCodeの設定を変更し、「同期」ボタンを利用

同期ボタンの設定を変えることでも、対応が可能です。
VSCodeの設定で「同期=rebase」にする

設定 → 検索バーに rebase と入力
Git: Pull Rebase をオン(git.pullRebase: true)
Git: Rebase When Sync をオン(git.rebaseWhenSync: true)

まとめ

「同期」= git pull → git push。既定は merge なので分岐時はマージコミットが生まれる。
意図的に避けるなら:
その場だけ → git pull --rebase
常にに避けたい → VS Code 設定で Pull Rebase / Rebase When Sync をオ

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?