メモの日々


2017年01月10日(火) [長年日記]

[dev][howto] Gitでブランチのマージを取り消してやり直す

Gitでブランチのマージを取り消し、ブランチを修正して再度マージする方法をメモ。マージ元のブランチをbranch1、マージ先のブランチをmasterとする。

マージの取り消し

[master] ---o---o---M---x
	           /
[branch1]  ---A---B

Mでbranch1をmasterへマージしたけどこれを取り消したい。このときはgit revertを使うのが簡単そう。

% git checkout master
% git revert -m 1 M

これで

[master] ---o---o---M---x---W
	           /
[branch1]  ---A---B

という状態になって、masterにMで入った変更は元に戻る。マージコミットに対するgit revertには-mオプションが必要なのが面倒。-m 1がデフォルトではいかんのか。

ブランチをもう一度マージする

上の後でbranch1に修正を加えて再びmasterへマージするにはどうするか。

[master] ---o---o---M---x---W---x---?
	           /               /
[branch1]  ---A---B-----------C---D

普通にマージしてしまうとAとBの変更がmasterにマージされない。

Undoing MergesにあるようにmasterブランチにWを取り消すコミットをした後でbranch1をmasterへマージすればいいみたいだけれど、マージの直前にmasterを更新するというのは危ういと感じる。マージし忘れる可能性があるから。

git revertのマニュアルからリンクされているrevert-a-faulty-merge.txtを読めば理解が進むと思われるが長いので読んでいない。

にあるようにWをbranch1に取り込んだ後でbranch1上でWを取り消すというのはいいように思ったのだけれど、試してみるとこうしてもAとBの変更はmasterに反映されなかった。なんでや。

なので、「ブランチをもう一度マージする」いい方法はわからない。

新しいブランチでやり直す

仕方ないので、マージのやり直しは次のように新しいbranch2を作って行えばいいと思う。

[master] ---o---o---M---x---W
	           /         \
[branch1]  ---A---B           \
                               \
[branch2]                       R

branch2ではRでWを取り消す。こうすればAとBが復活する。

% git checkout master
% git branch -b branch2
% git revert W

そのあとでCとDの変更をしてNでマージする。

[master] ---o---o---M---x---W---x-----------N
	           /         \             /
[branch1]  ---A---B           \           /
                               \         /
[branch2]                       R---C---D
(CとDのコミットをした後)
% git checkout master
% git merge branch2

2017年01月11日(水) [長年日記]

[unix][howto] ファイル同士のの引き算

ファイルAには存在するがファイルBには存在しない行を知りたいことがあった。どうするのがいいのだろう。

grepで頑張る

% grep -v -F -x -f B A

とすれば目的を達せられる感じ。オプションの意味をJMから引用。

-v, --invert-match

マッチの意味を逆にして、マッチしない行を抜き出して表示します。 (-v オプションは POSIX で規定されています)

-F, --fixed-strings

PATTERN を改行で区切られた固定文字列 (訳注: すなわち、正規表現ではない ただの文字列) のリストとして扱い、 その文字列のどれかとマッチするかを調べます。 (-F オプションは POSIX で規定されています)

-x, --line-regexp

パターンが行全体とぴったりマッチしたときにのみ、その行を選択します。 (-x オプションは POSIX で規定されています)

-f FILE, --file=FILE

パターンを FILE から 1 行 1 パターンとして読み込みます。 空のファイルはパターンを含まないので、何にもマッチしません。 (-f オプションは POSIX で規定されています)

簡単な例。

% cat A
pen
pineapple
apple
pen

% cat B
apple
google

% grep -v -F -x -f B A
pen
pineapple
pen

diffで頑張る

行の順番が入れ替わってもよければdiff(とsortとgrep)を使う手もありそう。

% diff -u <(sort A) <(sort B) | grep '^-'
--- /dev/fd/63  2017-01-11 19:02:44.127377698 +0900
-pen
-pen
-pineapple

余計な行や行頭文字が付いてしまうけれど。場合に依るだろうけど、試したケース(AとBが大きなファイルの場合)ではこちらの方がgrepだけで頑張るよりだいぶ速かった。


2017年01月12日(木) [長年日記]

[howto][windows] pacmanを使う

MSYS2を使っている。MSYS2はパッケージ管理にpacmanを使っているのでpacmanの使い方を覚えないといけない。基本的なことだけメモ。

オペレーション

pacmanはまず「オペレーション」を指定して、その後にオペレーション用のオプションを指定するスタイルみたい。

$ pacman --help
使用方法:  pacman <オペレーション> [...]
オペレーション:
    pacman {-h --help}
    pacman {-V --version}
    pacman {-D --database} <オプション> <パッケージ>
    pacman {-F --files}    [オプション] [パッケージ]
    pacman {-Q --query}    [オプション] [パッケージ]
    pacman {-R --remove}   [オプション] <パッケージ>
    pacman {-S --sync}     [オプション] [パッケージ]
    pacman {-T --deptest}  [オプション] [パッケージ]
    pacman {-U --upgrade}  [オプション] <ファイル>

オペレーションと一緒に 'pacman {-h --help}' を使うことでオプションを一覧できます

インストール済みパッケージの一覧表示

--query オペレーションに何もオプションを与えなければインストール済みパッケージの一覧が表示される。

$ pacman -Q
bash 4.3.046-1
bash-completion 2.3-1
(省略)
xz 5.2.2-1
zlib 1.2.8-3

インストール済みパッケージの更新

パッケージを一括更新するには --sync オペレーションに --refresh, --sysupgrade オプションを与える。

$ pacman -Syu
:: パッケージデータベースの同期中...
 mingw32 は最新です
 mingw64 は最新です
 msys は最新です
:: Starting core system upgrade...
 何も行うことがありません
:: システム全体の更新を開始...
 何も行うことがありません

リポジトリ上のパッケージの一覧表示

リポジトリ上のパッケージを表示するのにも --sync オペレーションを使うみたい。--list オプションを与える。

$ pacman -Sl
mingw32 mingw-w64-i686-OpenSceneGraph 3.5.3-2
mingw32 mingw-w64-i686-OpenSceneGraph-debug 3.5.3-2
(省略)
msys zsh 5.1.1-1
msys zsh-doc 5.1.1-1

リポジトリ上のパッケージの説明を表示

パッケージの説明は --sync オペレーションに --info オプションとパッケージ名を指定すると表示できる。--infoを2回指定すると表示される情報が少し増えるみたい。

$ pacman -Sii gcc
リポジトリ             : msys
名前                   : gcc
バージョン             : 5.3.0-3
説明                   : The GNU Compiler Collection - C and C++ frontends
アーキテクチャ         : x86_64
URL                    : http://gcc.gnu.org
ライセンス             : GPL  LGPL  FDL  custom
グループ               : msys2-devel
提供                   : なし
依存パッケージ         : gcc-libs=5.3.0-3  binutils  gmp  isl  mpc  mpfr  msys2-runtime-devel  msys2-w32api-headers  msys2-w32api-runtime  windows-default-manifest
提案パッケージ         : なし
必要パッケージ         : bc  gcc-fortran  llvm-svn
任意パッケージ         : なし
衝突パッケージ         : なし
置換パッケージ         : なし
ダウンロード容量       : 21.73 MiB
インストール容量       : 88.76 MiB
パッケージ作成者       : Alexey Pavlov <alexpux@gmail.com>
ビルド日時             : 2016年04月01日 05時07分40秒
MD5 Sum                : 77e38c3f73668ebe8b0b4b634944b54d
SHA-256 Sum            : 61fdb8e212dbb60b9f2d6ed96390f9a4ed22ea9afa65604b96f1936810673420
署名                   : 5F92EFC1A47D45A1

パッケージのインストール

パッケージのインストールをするのも --sync オペレーション。パッケージ名を与える。

$ pacman -S gcc
依存関係を解決しています...
衝突するパッケージがないか確認しています...

パッケージ (8) binutils-2.25.1-2  isl-0.16.1-1  mpc-1.0.3-1  msys2-runtime-devel-2.6.0-1  msys2-w32api-headers-5.0.0.4732.6172d2f-1  msys2-w32api-runtime-5.0.0.4732.6172d2f-1
               windows-default-manifest-6.4-1  gcc-5.3.0-3

合計ダウンロード容量:   36.57 MiB
合計インストール容量:  250.96 MiB

:: インストールを行いますか? [Y/n]

パッケージのアンインストール

パッケージのアンインストールには --remove オペレーションを使う。

何もオプションを指定しないと

$ pacman -R gcc
依存関係を確認しています...

パッケージ (1) gcc-5.3.0-3

合計削除容量:  88.76 MiB

:: 以上のパッケージを削除しますか? [Y/n]

のように依存パッケージを削除してくれない。依存パッケージを削除するには --recursive オプションを付ける必要がある。

$ pacman -Rs gcc
依存関係を確認しています...

パッケージ (8) binutils-2.25.1-2  isl-0.16.1-1  mpc-1.0.3-1  msys2-runtime-devel-2.6.0-1  msys2-w32api-headers-5.0.0.4732.6172d2f-1  msys2-w32api-runtime-5.0.0.4732.6172d2f-1
               windows-default-manifest-6.4-1  gcc-5.3.0-3

合計削除容量:  250.96 MiB

:: 以上のパッケージを削除しますか? [Y/n]