時短の為のSubversionコマンドおぼえがき

この記事は [Qiita x Code Polaris共催！女性ITエンジニアが作るアドベントカレンダー Advent Calendar 2022](https://qiita.com/advent-calendar/2022/qiita-code-polaris) 向けに書いたものです。

<!-- textlint-disable japanese/no-doubled-joshi -->
昨日(2022/12/01)は @mikako0115 さんの「[PySimpleGUIでGUIツール作成～Plotlyで月間支出グラフを出力してみよう](https://qiita.com/mikako0115/items/7bddef252154e544dd41)」でした。
<!-- textlint-enable japanese/no-doubled-joshi -->

----

<details><summary>まだお世話になっている理由</summary>

ゲーム制作には大小のバイナリファイルが山となります。
どのバイナリファイルが、いつ適用されたのか(あるいは、実装されたのか)というのは重要な情報です。

GitであればGit LFSが採用される現場もあるでしょうが、主にバイナリファイルを更新するのはエンジニアではありません。
その為、エンジニア以外の人々がGitに慣れているかいないかで判断することがあります。

(あと、Git LFSの構築がよくわからな…おっと誰か来たようだ)

</details>


<details><summary>何故コマンド？</summary>

<!-- textlint-disable ja-technical-writing/ja-no-mixed-period -->
ゲーム制作の現場は、そのほとんどがWindows環境です。ゲーミングPCバンザイ🙌
<!-- textlint-enable ja-technical-writing/ja-no-mixed-period -->

その為、作業者の大半はSubversionの操作に[TotoiseSVN](https://tortoisesvn.net/)を選択します。

ただしGUIツールの欠点として、Subversionのコマンドがすべて使えるわけではない、というのがあります。

作業によってはコマンド一行で終わるものがあります。あるいは'&&'で繋げたり、shellまたはバッチファイルで済ませたり…。

つまり時短ができるかも知れません。
これはその覚え書きです。

</details>


## 作業者がよく使うコマンド

### 今手元にあるやつを反映する

```bash
svn add .
svn commit -m "仕様変更: 回復アイテムをうどんからラーメンに変更"
```

<details><summary>svn add</summary>

`svn add .` で今のディレクトリ以下の変更全てをステージングします。

</details>

<details><summary>svn commit</summary>

その後、`svn commit` でサーバにアップロードします。

`-m` はコミットメッセージです。
オプションがない場合、メッセージのないままサーバにアップロードします。

</details>



### 作業中のものも全部吹き飛ばしてでも、最新の状態にする

```bash
svn cleanup --remove-unversioned --remove-ignored --vacuum-pristines
svn revert --recursive .
svn update --set-depth infinity
```

<!-- textlint-disable ja-technical-writing/ja-no-mixed-period -->
リビジョン番号指定版
<!-- textlint-enable ja-technical-writing/ja-no-mixed-period -->
```bash
svn cleanup --remove-unversioned --remove-ignored --vacuum-pristines
svn revert --recursive .
svn update --set-depth infinity -r <リビジョン番号>
```
<details><summary>svn cleanup</summary>

例えば `svn update` の途中で中断したために発生した断片的な更新情報を一度リセットするときに使います。
`--remove-unversioned` はバージョン管理されていないファイルを削除します。
`--remove-ignored` は`svn:ignore`が情報としてついているファイルを削除します
`--vacuum-pristines` は、_.svn_フォルダにある、もう参照されていないファイルを削除します。

</details>


<details><summary>svn revert</summary>

`svn revert` でカレントディレクトリの変更を破棄します。
オプション `--recursive` は再帰的を表します。
最後にディレクトリのパス `.` を入れます。

</details>


<details><summary>svn update</summary>

`svn update` でカレントディレクトリにあるバージョンを変更します。
オプションが何もついていない場合は、サーバにある最新のリビジョン番号を使用して更新されます。
`-r` または `--revision` の後に番号を入れると、指定されたリビジョン番号にバージョンをあわせます。

</details>


## マージ作業で使うコマンド

たまに失敗して、諦めてブランチを切っちゃうんですよね…。



#### カレントディレクトリのリポジトリのリビジョン番号の取得

```bash
svn log --stop-on-copy
```
現在のディレクトリの、最後のリビジョン番号を取得します。
これがないと、指定されたリビジョン番号までのマージができません。


#### マージ、ただしマージ先の変更で上書きする

```bash
svn merge \
    -r <今のリビジョン番号より1つ前>:<マージするリビジョン番号> \
    --depth infinity \
    --accept theirs-full \
    <URL>
```

`svn merge` コマンドによって、指定したURLまたはディレクトリにある変更を取り込みます。

`-r` 以降で、指定したリビジョンの範囲の変更をマージします。
引数の書き方は `<今のリビジョン番号より1つ前>:<マージするリビジョン番号>` です。

`--depth` はマージするディレクトリの深度を示します。
`infinity` は再帰的という意味です。

`--accept` は競合が発生した際、どちらを取り込むかを示します。
`theirs-full` はマージする方、この場合 `<URL>` にある情報で上書きします。
ただし、(これはどうしてかはわかりませんが) カレントディレクトリと `<URL>`の両方で削除しているとぶつかってしまうようです。

#### サーバーに反映
最後に `svn commit` でマージ情報をサーバに反映します。

```bash
svn commit -m "merge revision <マージするリビジョン番号> from <今のリビジョン番号>"
```



# 参考

- [【svn】基本コマンド - Qiita](https://qiita.com/konweb/items/6effd36aab551b2d6b8f)
- [svnコマンドでマージする - 作業ノート](https://te2u.hatenablog.jp/entry/20091222/p1)
- [Subversionでtrunkの内容をbranchにmergeまたはその逆 - 常水商会::よしなしごと](https://cockatiel-cage.hateblo.jp/entry/2012/12/14/122449)