gitについていろいろ調べていたら、Gitlessというgitのわかりにくい部分をシンプルにするツールを見つけましたが、日本語ドキュメントが現在(2017/02/19)さっぱりなかったので、勉強のために公式サイトの紹介ページを和訳してみました。
Google翻訳を多用しており、残りは意訳しています。Gitless自体理解しきれていないためよくわからずに訳した部分もあります。それは違うよ!という部分がありましたらコメントにてご指摘いただけると幸いです。
※ Gitless vs. Gitの比較画像はうまい載せ方を見つけられずに翻訳できていません。ご容赦くださいm(_ _)m
※ 本文に出てくる実行画面の部分は訳さずに載せています。<*数字>は原文にはありません。
#About
Gitlessは、Git上に構築されたバージョン管理システムです。
多くの人がGitは使いにくいと訴えています。私たちは、Gitの基本的なシステムの中で、ユーザインタフェースよりも深い場所に問題はあると考えています。
Gitlessは、基本的なシステムを変更するベニア板をアプリケーション上に置くとどうなるかを調べるための実験です。GitlessはGit上に実装されているので(いわゆるGitのプロが「磁器」と呼ぶものです)、いつでもGitに戻ることができます。
もちろん、あなたとリポジトリを共有している同僚が、あなたがGitの愛好家ではないことを知ることは決してありません。
Gitlessを開始するには、Documentationをチェックしてください。
- バージョン管理を初めてお使いの方は、Documentationを十分に活用して始めてください。
- あなたが愛するGitとは何が違うのかを見たいGitのプロの方は、Gitless vs. Gitで違いを見つけることができます。
- ソフトウェアデザインに興味があり、Gitlessの研究についてもっと学びたい場合は、Researchを参照してください。
#Documentation
目次:Interface、リポジトリの作成、コミット、ブランチ、タグ付け、リモートリポジトリの操作
-
gl init
- 空のリポジトリを作成、または既存のリモートリポジトリからリポジトリを作成する -
gl status
- リポジトリのステータスを表示する -
gl track
- ファイルへの変更の追跡を開始する -
gl untrack
- ファイルへの変更の追跡を停止する -
gl diff
- ファイルへの変更の比較を表示する -
gl commit
- ローカルリポジトリの変更を記録する -
gl checkout
- コミットされたバージョンのファイルにチェックアウトする -
gl history
- コミット履歴を表示する -
gl branch
- ブランチの一覧表示、作成、編集または削除をする -
gl switch
- ブランチを切り替える -
gl tag
- タグの一覧表示、作成または削除をする -
gl merge
- あるブランチの変更を別のブランチにマージする -
gl fuse
- あるブランチの変更を別のブランチにヒューズする -
gl resolve
- コンフリクトを解決したファイルにマークを付ける -
gl publish
- アップストリームにコミットを公開する -
gl remote
- リモートの一覧表示、作成、編集または削除をする
##リポジトリの作成
"foo"ディレクトリをリポジトリにしたいとします。これは、gl init
コマンドで行います。これにより、現在の作業ディレクトリが空のリポジトリに変換され、foo
内ファイルの変更の保存を開始する準備が整いました。
$ mkdir foo
$ cd foo/
$ gl init
✔ Local repo created in /MyFiles/foo *1
*1 ローカルリポジトリ/MyFiles/foo
を作成しました
ほとんどの場合、空のリポジトリで作業を始めるのではなく、既存のリモートリポジトリをクローンして作業をしたいでしょう。
リモートリポジトリをクローンをローカルに作成するには、同じgl init
コマンドの後にリポジトリのURLを与えることで実現できます。
$ mkdir experiment
$ cd experiment/
$ gl init https://github.com/spderosso/experiment
✔ Local repo created in /MyFiles/experiment *2
✔ Initialized from remote https://github.com/spderosso/experiment *3
*2 ローカルリポジトリ/MyFiles/experiment
を作成しました
*3 リモートリポジトリhttps://github.com/spderosso/experiment
から初期化しました
##コミット
これでローカルリポジトリが完成しましたので、ファイルへの変更の保存を開始しましょう。Gitlessのファイルは、 tracked、untracked、またはignoreすることができます。
- tracked fileは、Gitlessが変更を検出するファイルです。追跡されたファイルは変更があった場合、自動的にコミットの対象になり(gitで言うadd)、ステータスの「Tracked files with modifications」セクションに表示されます。
- untracked fileは、Gitlessが変更を検出しないファイルです。これらは自動的にはコミットの対象にはならず、ステータスの「Untracked files」セクションに表示されます。
- ignore fileは、Gitlessによって完全に無視されるファイルであり、ステータスの出力に現れません。
gl status
コマンドの出力例です。foo.py
とbar.py
は変更が加えられたtracked file、.gitignore
は変更が加えられていないtracked file、baz.py
はuntracked file、foo.pyc
はignore file です
$ ls
bar.py baz.py foo.py foo.pyc .gitignore
$ gl status
On branch master, repo-directory //
Tracked files with modifications: *4
➜ these will be automatically considered for commit
➜ use gl untrack <f> if you don't want to track changes to file f
➜ if file f was committed before, use gl checkout <f> to discard local changes
foo.py
bar.py
Untracked files: *5
➜ these won't be considered for commit)
➜ use gl track <f> if you want to track changes to file f
baz.py
変更が加えられた追跡ファイル:
➜ これらは自動的にコミットの対象になります
➜ ファイル<f>の変更を追跡したくない場合は、gl untrack <f>を使用します
➜ 以前にファイル<f>がコミットされている場合は、gl checkout <f>を使用してローカル変更を破棄します
追跡されていないファイル:
➜ これらはコミットの対象にはなりません
➜ ファイル<f>の変更を追跡する場合は、gl track <f>を使用します
さて、これらの3つの異なる状態の間でファイルはどのように動くのでしょう?
.gitignoreファイルに記述されているignore指定と一致するファイルは無視されます。上記の例では、内容が *.pyc
の.gitignoreファイルがあります。foo.pyc
はそのパターンと一致しているので無視されます。
ignore specでマッチしない新しいファイルは、最初はuntracked fileです。あなたがそれを追跡したいならば、gl track
コマンドでそれを行うことができます。gl untrack
コマンドを使用すると、追跡されたファイルに対する変更の追跡を停止することができます。gl checkout
コマンドを使用すると、ファイルを以前のバージョンにいつでも戻すことができます。
$ gl track baz.py
✔ File baz.py is now a tracked file *6
$ gl track baz.py
✘ File baz.py is already a tracked file *7
$ gl untrack baz.py
✔ File baz.py is now an untracked file *8
$ gl checkout foo.py
You have uncommitted changes in foo.py that would be overwritten by checkout. Do you wish to continue? (y/N) *9
> y
✔ File foo.py checked out successfully to its state at HEAD *10
*6 ファイルbaz.py
は追跡されたファイルになりました
*7 ファイルbaz.py
は既に追跡されたファイルです
*8 ファイルbaz.py
が非追跡ファイルになりました
*9 チェックアウトによって上書きされるコミットされていないfoo.py
の変更があります。続行しますか?(y/N)
*10 ファイルfoo.py
がHEADの状態に正常にチェックアウトされました
ファイルへの変更を保存するには、gl commit
コマンドを使用します。
デフォルトでは、変更されたすべての変更ファイルはコミットされますが、o/only
、e/exclude
、およびi/include
フラグを使用して、コミットするファイルのセットをカスタマイズできます。
$ gl commit -m "foo and bar"
$ gl commit -m "only foo" -o foo.py
$ gl commit -m "only foo and baz" -o foo.py baz.py
$ gl commit -m "only foo" -e bar.py
$ gl commit -m "only foo and baz" -e bar.py -i baz.py
$ gl commit -m "foo, bar and baz" -I baz.py
コミットするファイルのセグメントをインタラクティブに選択できるp/partial
フラグもあります。
gl diff
コマンドを使用して、作業バージョンとコミット済みバージョンのファイルの違いを確認することができます。コミットのように、diffのデフォルトのファイルセットはすべての変更されたファイルのセットですが、o/only
、e/exclude
、およびi/include
フラグでカスタマイズできます。
ファイルの削除は、OSの機能(Unixのrmコマンドを使用するなど)を利用して簡単に行えます。Gitlessでは、ファイルが追跡されている場合に削除を検出し、ステータスで削除されたものとしてに表示します。
Gitlessは現在、名前の変更を検出しません。ファイルの名前を変更した場合、Gitlessでは古い名前のファイルが削除され、新しい名前と内容の新しいファイルが作成されたとして解釈します。名前を変更したファイルを再び追跡するには、gl track
をする必要があります。
##ブランチ
ブランチは独立した開発ラインです。 あなたは常になにかしらのブランチで作業しています。各ブランチには独自の履歴があります(gl history
コマンドで見ることができます)。ブランチを切り替えると、既存のファイルやブランチ上に作成した新しいファイルに対する変更は、他のブランチには反映されません。
新しいブランチを作成するには、gl branch
コマンドを使用します。 別のブランチに切り替えるには、gl switch
コマンドを使用します。
$ gl branch -c develop
✔ Created new branch develop *11
$ gl switch develop
✔ Switched to branch develop *12
*11 新しいブランチ"develop"を作成しました
*12 ブランチ"develop"に切り替えしました
すべてのブランチ一覧の表示するには:
$ gl branch
List of branches:
➜ do gl branch <b> to create branch b
➜ do gl branch -d <b> to delete branch b
➜ do gl switch <b> to switch to branch b
➜ * = current branch *13
* master
develop
*13 *は現在のブランチ
各ブランチにはHEADがあり、そのブランチで最後にコミットされたものです。デフォルトでは、新しいブランチの先頭は現在のブランチのHEADと等しくなります。別のコミットを新しいブランチの頭にしたい場合は、dp/divergent-point
フラグを与えることで可能です。
コミットを指定するには、そのIDを使用するか、"~"を使用して祖先参照で指定できます。HEAD~n
は、HEADより前のn番目のコミットを参照します。
現在のブランチのHEADを変更するには、sh/set-head
フラグを使用します。shフラグは、例えば最後のコミットを修正するのに便利です。そうするには、gl branch -sh HEAD~1
を実行します。現在のブランチのHEADを変更しても作業ディレクトリには反映されませんが、さらに作業ディレクトリを新しいHEADと一致するようにリセットしたい場合は、gl checkout
を使用します。
最終的にブランチは最終的に変化していくでしょう。あるブランチから現在のブランチに変更を加えるには、mergeとfuseの2つの方法があります。
###merge
あるブランチの変更を現在のブランチにマージするには、gl merge develop
を行います。これにより、現在のブランチの変更に加えて、developブランチの変更を含む新しいマージコミットが作成されます。
###fuse
ブランチをヒューズすると、マージよりもコントロールがしやすくなります。
あるブランチからの変更を現在のブランチにヒューズするときに、ヒューズするコミットと挿入場所を指定することができます。デフォルトでは、すべてのブランチがヒューズされると、挿入場所は分岐点(あるブランチが現在のブランチから分岐したポイント)になります。
たとえば、次の図は、2つのブランチが存在する状況を示しています。master(現在のブランチ)とdevelopです。2つのブランチが共通している最後のコミットは"A"です。このコミットは「分岐点」(masterとdevelopの分岐点であるため)です。gl fuse development
を実行した後、開発中のコミットは、masterの分岐点の後ろに挿入されます。
他の挿入場所を選択するには、ip/insertion-point
フラグを使用します。コミットID、HEADまたはdp/divergent-point
を与えることができます。
o/only
またはe/exclude
フラグを使用して、ヒューズされるコミットのセットをカスタマイズできます。
このプロセス中にコンフリクトが発生する可能性があります。その場合、gl status
コマンドはそれに応じて変更され、競合しているファイルを示します。競合したファイルを編集すると、gl resolve
(ファイル名を与えるとそれをマークする)で解決されたものとしてマークされます。すべての競合が解消されたら、"gl commit"を実行してヒューズまたはマージを続けます。
ブランチは「アップストリームブランチ」を持つことができます。ブランチにアップストリームが関連付けられている場合、gl fuse
またはgl merge
をgl {fuse、merge} upstream_branch
の略記として使用できます。現在のブランチのアップストリームブランチを設定するには、gl branch -su <upstream_branch>
を使用します。
##タグ付け
コミットが何らかの形で特別であることを示すためにタグを使用します。たとえば、gl tag
を使用して「v1.0」という名前のタグを作成し、リリースv1.0を表すコミットを指すようにすることができます。
$ gl tag -c v1.0
✔ Created new tag v1.0 *14
*14 新しいタグv1.0を作成した
この場合タグは現在のブランチの先頭を指しますが、ci/commit
フラグを付けて他のコミットにタグ付けすることもできます。
$ gl tag
List of tags:
➜ do gl tag <t> to create tag t *15
➜ do gl tag -d <t> to delete tag t *16
v1.0 ➜ tags 311bf7c Ready to release
*15 gl tag <t>
でタグtを作成します
*16 gl tag -d <t>
でタグtを削除します
###リモートリポジトリの操作###
リモートリポジトリを参照するのに、そのURLを常に使用することができますが、より簡単な方法はgl remote
コマンドでリポジトリを "リモート"として追加することです。
$ gl remote -c experiment https://github.com/spderosso/experiment
✔ Remote experiment mapping to https://github.com/spderosso/experiment created *17
successfully
➜ to list existing remotes do gl remote *18
➜ to remove experiment do gl remote -d experiment *19
*17 リモートリポジトリhttps://github.com/spderosso/experiment
へのリモート"experiment"を作成しました
*18 gl remote
で既存のリモート一覧を表示します
*19 gl remote -d experiment
でリモート"experiment"を削除します
これで、 "experiment"を使ってこのリモートリポジトリを参照し、 experiment/some-branch
を使用して、 "experiment"に存在する"some-branch"のブランチを参照することができます。
###変更をダウンロードする
リモートブランチからの変更をヒューズまたはマージすることも可能です。たとえば、gl merge experiment/master
を実行すると、ローカルブランチに存在しないリモートブランチの変更がマージされます。また、gl fuse
を使用することもできます。
###変更のアップロードする
アップストリームで変更を送信するには、gl publish
を使用します。パブリッシュコマンドは、入力を与えられていない場合、デフォルトで現在のブランチのアップストリームブランチを更新します。
###作成、削除、または一覧表示
リモートブランチを作成、削除、または一覧表示するには、ローカルブランチに使用するのと同じgl branch
コマンドを使用します。
"gl branch -c experiment/develop"を実行すると、リモート"experiment"に存在する"develop"ブランチが作成されます。デフォルトでは、この新しいブランチのHEADは現在のブランチのHEADと等しくなるので、リモートに存在しないすべてのコミットがアップロードされることに注意してください。
リモートブランチを表示するには、 gl branch
の r/remote
フラグを使用します。
###タグの作成、削除、または一覧表示
リモートタグを作成、削除、または一覧表示するには、gl tag
コマンドを使用します。
gl tag -c experiment/v1.0
を実行すると、リモートの"experiment"に新しいタグv1.0が作成されます。
gl tag
のr/remote
フラグを使ってリモートのタグ一覧を表示することもできます。
リモートからローカルリポジトリを作成すると(gl initコマンドの入力としてURLを渡すことによって)、リモートブランチごとにローカルブランチが作成され、各ローカルブランチは、リモートをアップストリームとして自動的に設定されます。
#Gitless vs Git
##変更を保存する
Gitlessにはステージングエリアはありません。
これは、柔軟なコミットコマンドと組み合わせることで、リポジトリへの変更を非常に簡単に保存できます。
また、ファイルの分類を変更して、追跡したり、非追跡したり、無視したりすることもできます。ファイルがHEADに存在するかどうかは関係ありません。
##ブランチ
理解しなければならない主な点は、Gitlessではブランチが完全に独立した開発ラインであることです。各ブランチは、ファイルの作業バージョンを互いに分離して保持します。別のブランチに切り替えると、作業ディレクトリの内容が保存され、切り替え先のブランチに対応する内容が取得されます。ファイルの分類も保存されます(ファイルは一部のブランチでは非追跡ですが、別のブランチでは追跡します、Gitlessはこれを覚えています)。
つまり、Gitlessでは、コミットされていない変更が切り替え先ブランチの変更と矛盾することを心配する必要はありません。
あなたがヒューズまたはマージの途中にいて、コンフリクトの解決を脇に置いておきたい場合は、そうすることができます。あなたがそのブランチに戻ったときにコンフリクトはそこにあります。
##リモートリポジトリの操作
Gitlessの他のリポジトリとの同期は、Gitと非常によく似ています。
-
Purposes, Concepts, Misfits, and a Redesign of Git
S. Perez De Rosso and D. Jackson. In Proceedings of the 2016 ACM SIGPLAN International Conference on Object-Oriented Programming, Systems, Languages, and Applications (OOPSLA 2016) -
What's Wrong with Git? A Conceptual Design Analysis
S. Perez De Rosso and D. Jackson. In Proceedings of the 2013 ACM International Symposium on New Ideas, New Paradigms, and Reflections on Programming & Software (Onward! 2013)