DockerのGUIをMacで使う
DockerコンテナのGUIアプリ(といってもxterm)をMacから使ってみました。
Quartz 2.7.11のインストール
QuartzからMacにダウンロードしてインストールします。
Quartzの設定
X11 - 環境設定でネットワークク・ライアントからの接続を許可をチェックしてX11を再起動する。

Quartzを起動するとxtermが起動するので下記のコマンドを実行してリモートからの接続を許可します。
$ xhost +
Dockerからの接続
コンテナにxtermをインストールして、下記のように実行します。
root@6497ba135950:/# useradd -m user root@6497ba135950:/# su - user user@cba17df706a0:~$ export DISPLAY=<MacのIPアドレス>:0 user@cba17df706a0:~$ xterm
これで、Dockerコンテナで実行したxtermがMac側に表示されます。
以上
gitのrebaseでコミットを書き換える
git rebaseでコミットをきれいにする方法です。
使うタイミング
自分専用のトピックブランチで作業が完了して 元のブランチに戻す前 に行います。
練習用のリポジトリ作成
sampleというファイルに機能が3つインプリされているという想定のテスト用のリポジトリを作成します。
$ git init test $ cd test $ for i in `seq 1 3`; do printf "func%d\n\n" $i; done > sample $ cat sample func1 func2 func3 $ git add sample; git commit -m "init" [master (root-commit) c509fc6] init 1 file changed, 6 insertions(+) create mode 100644 sample $
トピックブランチを作って、3つの機能の全てに修正を加えてコミットしたと想定します。
$ git checkout -b topic Switched to a new branch 'topic' $ sed -ie 's/\(func.\)/\1+fix/' sample $ cat sample func1+fix func2+fix func3+fix $ git commit -a -m "fix" [topic 77adf00] fix 1 file changed, 3 insertions(+), 3 deletions(-) $
この時点で、気がつけば、git reset HEADで戻すことも可能ですが、気が付いたときには、もう一つ機能が追加されていたとします。
$ echo func4 >> sample $ git commit -am "これは、正しいコミットで修正したくない" [topic e836500] これは、正しいコミットで修正したくない 1 file changed, 1 insertion(+) $
テスト用のリポジトリは、こんな感じになります。
$ git --no-pager log --pretty=oneline e836500e25943c80e67fcbfdcfef10e0d8fc0040 これは、正しいコミットで修正したくない 77adf00234c23ceda93be668eef460a218944f5a fix c509fc62f1a14a5d374c20203fecec670cf82a6f init $
コミットを分割する
3つの機能の修正は、独立しているので、修正毎に3つのコミットにするべきだったと想定して、コミットを分割します。
対象のコミットを確認する。
git show-branchコマンドで、現在のtopicブランチに2つのコミットがありtopic^に修正したいコミットがあることがわかります。
$ git show-branch ! [master] init * [topic] これは、正しいコミットで修正したくない -- * [topic] これは、正しいコミットで修正したくない * [topic^] fix +* [master] init $
対象のコミットを修正
git rebase -iを使って対象のコミットを修正します。
対象は、topic^なので、その一つ前のmasterを指定します。
$ git rebase -i master
エディタが開いて対象のコミットが下記のように表示されます。
pickとなっている部分で[e]を選択してエディタを押します。
pick 77adf00 fix
pick e836500 これは、正しいコミットで修正したくない
# Rebase c509fc6..e836500 onto c509fc6 (2 command(s))
修正したいコミットのpickがeditに変わったのを確認してエディタを修正します。
edit 77adf00 fix
pick e836500 これは、正しいコミットで修正したくない
# Rebase c509fc6..e836500 onto c509fc6 (2 command(s))
エディタが終了すると、こんなメッセージが表示されます。
Stopped at 77adf00234c23ceda93be668eef460a218944f5a... fix
You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
$
git resetで修正を戻します。
$ git reset HEAD^ Unstaged changes after reset: M sample $
修正内容を分割
git add -pを使って修正を分割します。
下記のように表示されるので、必要な修正まで[s]で分割していきます。
$ git add -p diff --git a/sample b/sample index bd073e0..b9dc832 100644 --- a/sample +++ b/sample @@ -1,6 +1,6 @@ -func1 +func1+fix -func2 +func2+fix -func3 +func3+fix Stage this hunk [y,n,q,a,d,/,s,e,?]?
[s]を押すと次のように、コミットが分割されます。
Stage this hunk [y,n,q,a,d,/,s,e,?]? s Split into 3 hunks. @@ -1,2 +1,2 @@ -func1 +func1+fix Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]?
[y]を押して、分割されたコミットがステージされた状態にします。
[q]を押して一旦、終了します。
Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]? y @@ -2,3 +2,3 @@ -func2 +func2+fix Stage this hunk [y,n,q,a,d,/,K,j,J,g,e,?]? q $
git statusで確認すると下記のようになります。
$ git status
interactive rebase in progress; onto c509fc6
Last command done (1 command done):
edit 77adf00 fix
Next command to do (1 remaining command):
pick e836500 これは、正しいコミットで修正したくない
(use "git rebase --edit-todo" to view and edit)
You are currently splitting a commit while rebasing branch 'topic' on 'c509fc6'.
(Once your working directory is clean, run "git rebase --continue")
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: sample
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: sample
$
下記のように分割したコミットだけがステージされるので、これを、あと2回繰り返して、3つのコミットに分割します。
$ git --no-pager diff --staged diff --git a/sample b/sample index bd073e0..604342d 100644 --- a/sample +++ b/sample @@ -1,4 +1,4 @@ -func1 +func1+fix func2 $ git --no-pager diff diff --git a/sample b/sample index 604342d..b9dc832 100644 --- a/sample +++ b/sample @@ -1,6 +1,6 @@ func1+fix -func2 +func2+fix -func3 +func3+fix $
ログが分割されたことを確認します。
$ git --no-pager log --pretty=oneline 04d8da4ce4057583d6b917f0b1e481211fdb207c func3 e780e2cbd878d6d7bc2c9dd99cb1e0cefc9131dc func2 8263453e933119f5397b96267425c357731120e0 func1 c509fc62f1a14a5d374c20203fecec670cf82a6f init $
git rebase --continueでログの修正を終了します。
$ git rebase --continue Successfully rebased and updated refs/heads/topic. $
これで、コミットが分割されました。
$ git show-branch ! [master] init * [topic] これは、正しいコミットで修正したくない -- * [topic] これは、正しいコミットで修正したくない * [topic^] func3 * [topic~2] func2 * [topic~3] func1 +* [master] init $
以上
systemdで設定を上書きする方法
systemdで設定を上書きするには、/etc/systemd/systemに設定します。
systemctl edit <サービス>コマンドがあります。
$ sudo systemctl edit <サービス名>.service
エディタが起動されて追加設定を書き込めます。
設定先は、/etc/systemd/system/<サービス名>.service.d/override.confです。
$ ls -l /etc/systemd/system/<サービス名>.service.d/ 合計 4 -rw-r--r-- 1 root root 27 11月 6 08:35 override.conf $
今まで、手動でやってました。
既存のgitリポジトリを短時間でコピーする。
既存のgitリポジトリを短時間でコピーする方法です。
ローカルにクローン
ブランチを指定して最新コミットに限定してクローンします。
$ git clone --depth 1 -b <ブランチ名> <URL>
リモートにプッシュ
$ git remote add origin <URL> $ git push origin <ブランチ名> ... ! [remote rejected] <ブランチ名> -> <ブランチ名> (shallow update not allowed) error: failed to push some refs to <URL> $
部分的にクローンしたgitリポジトリを--unshallowオプションでpush可能なリポジトリに変換します。
再度、pushします。
$ git fetch --unshallow $ git push origin <ブランチ名> Counting objects: 227, done. Compressing objects: 100% (97/97), done. Writing objects: 100% (227/227), 66.44 KiB | 0 bytes/s, done. Total 227 (delta 132), reused 214 (delta 129) To <URL> * [new branch] <ブランチ名> -> <ブランチ名> $
pythonの開発環境
pythonでちょっとしたテストをする際に独立した環境を準備する方法です。
virtualenvコマンドで独立したpython環境を作成して、direnvでcdするだけで環境の切り替えをすることが出来ます。
環境
初期設定
下記のパッケージをインストールします。
$ sudo apt install direnv python-virtualenv
.bashrcに下記の2行を追加します。(direnvの設定)
$ tail -2 ~/.bashrc export EDITOR=emacs eval "$(direnv hook bash)"
開発環境の作成
開発環境は、ディレクトリを作成して.envrcファイルを準備します。
$ mkdir sample $ cd sample $ direnv edit .
EDITORに指定したエディタが開くので必要な設定を追加します。
pythonのテスト環境をvirtualenvで準備する場合は、以下のように設定します。
$ direnv edit .
direnv: loading .envrc
Running virtualenv with interpreter /usr/bin/python2
New python executable in /home/ksaito/tmp/sample/plib/bin/python2
Also creating executable in /home/ksaito/tmp/sample/plib/bin/python
Installing setuptools, pkg_resources, pip, wheel...done.
direnv: export +VIRTUAL_ENV ~PATH
$ cat .envrc
PLIB=plib
ACTIVE=${PLIB}/bin/activate
if [ ! -e ${ACTIVE} ]
then
virtualenv --no-site-packages ${PLIB}
fi
. ${ACTIVE}
$
使い方
使うときには、ディレクトリに移動するだけです。
direnvでVIRTUAL_ENVとPAHTが追加され、pipでパッケージ一覧を表示すると4つしかないことが分かります。
$ cd sample direnv: loading .envrc direnv: export +VIRTUAL_ENV ~PATH $ pip list --format=legacy pip (9.0.0) pkg-resources (0.0.0) setuptools (28.7.1) wheel (0.30.0a0) $ pip list --format=legacy | wc -l 4 $
ディレクトリを移動すると自動的に設定はもとに戻ります。
パッケージは、32個あります。
$ cd .. direnv: unloading $ pip list | wc -l 32 $
direnvは、pythonに限らず利用できるのでとても便利です。
プロンプトを変えたかったのですが、PS1は設定しても無視されてしまう...
複数のディレクトリの差分と同期
複数の環境に共通のシェルやプログラムを配置することがあります。「全て同じはず」という言葉を信じる以外に確認方法がない場合、gitに移行する方法です。
bareリポジトリの作成
bareリポジトリを作ります。GitHubやbitbucketを使ってもokです。
$ git init --bare repo
$ cd serv1 $ git init $ git add . $ git commit -m "init" $ cd ../srv2 $ git init $ git add . $ git commit -m "init"
bareリポジトリにpushします。 同じことをserv2にも行います。
$ cd serv1 $ git remote add origin user@localhost:/tmp/bare $ git push -u origin master:serv1 $
bareリポジトリをclone
bareリポジトリをcloneして、serv1とserv2を、それぞれcheckoutします。
$ git clone user@localhost:/tmp/repo work $ cd work $ git checkout -b serv1 origin/serv1 $ git checkout -b serv2 origin/serv2 $
差分
serv1ブランチとserv2ブランチの差分を確認することで、違いが分かります。
$ git diff --name-status serv1 serv2 M readme.txt D src/scr2 $
serv1をチェックアウトして修正/テストする
テスト環境で特定のブランチをcloneして修正/テストします。
$ git clone -b serv1 user@localhost:/tmp/repo work $ cd work $ git branch -av * serv1 0640614 update2 remotes/origin/serv1 0640614 update2 remotes/origin/serv2 b7ab37e update $
テストが完了したらadd/commitしてpushします。
$ git add .
$ git status
On branch serv1
Your branch is up-to-date with 'origin/serv1'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: readme.txt
$ git commit -m "fix"
[serv1 554a8cb] fix
1 file changed, 1 insertion(+)
$ git push
$
リリース
serv1環境でpullしてタグ付けします。
$ cd serv1 $ git pull 0640614..554a8cb serv1 -> origin/serv1 * [new branch] serv2 -> origin/serv2 Updating 0640614..554a8cb Fast-forward readme.txt | 1 + 1 file changed, 1 insertion(+) $ git tag v1.1 $
ブランチをサーバ名、タグをリリースを特定する番号にすることで台帳+手作業をなくすことが出来ます。
以上