Closed6
VSCodeのGit拡張機能を使って、ブランチ間の差分を表示する
目的
VSCodeのソース管理の拡張機能では、ブランチ間の差分を表示できるものがある。
そういった拡張は多機能なものが多く、DevContainerを使ったリモート開発環境でもこの機能だけ利用可能したいので、自作できるか調査する。
作業
- VSCodeの拡張機能の開発環境作成
- VSCode APIでどういったことができるか調査
- 以前調べたとき、差分表示機能があることは確認済み
VSCodeの拡張機能の開発環境構築
動作確認にのみ利用。
開発環境
- OS: macOS Sonoma 14.6.1
- VSCode v1.93.1
- devbox 0.13.1
- node v22.8.0
- npm v10.8.2
devbox設定
# initialize devbox
devbox init
# install node.js
devbox add nodejs
# start devbox
devbox shell
テンプレート作成
npx --package yo --package generator-code -- yo code
VS Code API調査: 差分エディター
VSCodeの差分エディターを開く
vscode.diff - Opens the provided resources in the diff editor to compare their contents.
- left - Left-hand side resource of the diff editor
- right - Right-hand side resource of the diff editor
- title - Human readable title for the diff editor
- options - (optional) Either the column in which to open, or editor options (see vscode.TextDocumentShowOptions)
引数left
、right
には 比較するテキストを設定することはできなかった。
一時ファイルなどに保存し、URI形式で設定する。
await vscode.commands.executeCommand('vscode.diff',
vscode.Uri.file(file),
vscode.Uri.file(file2),
'diff'
)
VS Code API: Git拡張機能
ビルトインのGit拡張機能を利用して、VSCodeで開いているフォルダ内のリポジトリを操作できる。
公式のREADMEに記載の通り設定する。
- package.jsonに依存関係を設定
package.json
"extensionDependencies": [
"vscode.git"
]
- 定義ファイル
src/api/git.d.ts
をコピペする - 拡張機能で呼び出す例
- 各メソッドの説明は
src/api/git.d.ts
に記載がないため、メソッドから推測したり、上記リポジトリのコードを調べる。
- 各メソッドの説明は
extension.ts
import { type GitExtension } from './git'
const gitExtension = vscode.extensions.getExtension<GitExtension>('vscode.git').exports
const git = gitExtension.getAPI(1)
ブランチ間の比較方法の調査
まず、gitコマンドでの実施方法を調べる。
今回のやりたいコマンドはgit diff ブランチ名1..ブランチ名2
の形式で実現可能。
差分はVSCodeの差分エディタで表示するので、ファイル名のみ取得する。
git diff --name-only branch1..branch2
前述のVSCodeのGit機能でこの機能があるか確認した。
メソッド名からRepository.diffBetween
を試してみたが、出力内容はgit diff
の結果と異なった。
git.d.ts
export interface Repository {
diffBetween(ref1: string, ref2: string): Promise<Change[]>;
}
ソースコードを確認したところ、git diff ref1...ref2
のコマンドを実行していた(.
の数が異なる)。
ここはVSCodeのGit機能は対応していない、と判断し、node.js経由でgitコマンドを直接実行する。
# Git 1.8.5以降
git -C <リポジトリのパス> <コマンド>
extension.ts
import * as vscode from 'vscode'
import { Branch, Repository, type GitExtension } from './git'
import { execSync } from 'child_process'
import os from 'os'
...(省略)
const gitExtension = vscode.extensions.getExtension<GitExtension>('vscode.git')?.exports
const git = gitExtension?.getAPI(1)
if (!git) return
// VSCodeで開いているフォルダからローカルブランチを取得
const repo: Repository = git.repositories[0] // TODO: UIでユーザに選択させる
const branches: Branch[] = await repo.getBranches({ remote: false })
// git diff --name-only branch1..branch2
// TODO: UIでユーザに選択させる
const src = branches[0].name!
const dist = branches[1].name!
// Git 1.8.5以上で実行可能
const args = ['git', '-C', repo.rootUri.path, 'diff', '--name-only', `${src}..${dist}`]
const stdout = execSync(args.join(' '))
// 差分のあるファイルを取得
const files = stdout.toString().split(os.EOL)
比較するファイルを取得し、差分エディターで表示する
各ブランチのファイルを取得する
いずれかの方法でファイルの内容を取得し、一時フォルダや拡張機能のフォルダ内に保存する。
- git コマンド
git show ブランチ名:ファイル名
- VSCodeのGit機能
export interface Repository {
show(ref: string, path: string): Promise<string>;
}
保存したファイルを差分エディターで表示
await vscode.commands.executeCommand('vscode.diff',
vscode.Uri.file(file),
vscode.Uri.file(file2),
'diff'
)
このスクラップは3ヶ月前にクローズされました