Content from 自動的なバージョン管理


最終更新日:2024-03-28 | ページの編集

概要

質問

  • バージョン管理とは何で、なぜそれを使うべきなのでしょうか?

目的

  • 自動バージョン管理システムの利点を理解しましょう。
  • 自動バージョン管理システムの仕組みの基本を理解しましょう。

それではまず、どのようにしてバージョン管理システムが 「いつ」、「何」を、「誰」が編集したのかを記録・管理しているかを見ていきましょう。 他の人と共同作業をしていなくても、 以下の状況に陥るより、自動的なバージョン管理を使うほうが大分良いはずです:

Comic: a PhD student sends "FINAL.doc" to their supervisor, but after several increasingly intense and frustrating rounds of comments and revisions they end up with a file named "FINAL_rev.22.comments49.corrections.10.#@$%WHYDIDCOMETOGRADSCHOOL????.doc"
「高く、深く積み上げる」Jorge Cham 作、 https://www.phdcomics.com

皆さんもこんな経験をされたことがあるはずです。複数の、(それもほとんど 内容が同じの)文書のコピーを保存しておくのは馬鹿げたことです。 文書作成ソフトの中には、例えばMicrosoft Wordの変更履歴、Google Docsのバージョン履歴、LibreOfficeの変更の記録・表示、こういった状況にある程度うまく対応できるものもあります。

バージョン管理システムは、基礎となるドキュメントを元に、 加えられた全ての変更点を記録していきます。 バージョン管理システムは、基礎となるドキュメントを元に、 加えられた全ての変更点を記録していきます。ドキュメントの 進歩を記録していると考えてもらって構いません。変更点を最初の状況まで 戻してから、最新版になるまでの変更を一つずつ再現していくことができます。

変更は連続して保存されます

「変更点」と「ドキュメント」を別々の物として考えてみると、基礎となるドキュメントに 異なる変更点を「再現」する事によって、結果的に違ったバージョンのドキュメントを 作る事が可能だという事が分かります。 例えば、下の図のように二人のユーザーが同じドキュメントに違った編集を加えた場合です。

異なるバージョンの保存ができます

変更点の衝突(コンフリクト)が無ければ、二つ以上の違った変更点を基礎ドキュメントに加えることさえできます。

複数のバージョンをマージできます

バージョン管理システムは、ユーザーがドキュメントに加えた変更点を記録するツールであり、 結果的にドキュメントの違ったバージョンを作成する事ができます。 このツールを活用 する事によって、次のバージョンに加える変更点(個々の変更点は 「commit(コミット)」と呼びます)を決める事ができ、変更点に関するメタデータも一緒に保存する事ができます。 特定のプロジェクトのコミット履歴とそれに関するメタデータを総じて 「repository(リポジトリ)」と呼びます。 リポジトリは 別々のコンピュータと同期させる事が出来るので、他人との共同作業を潤滑に進めることが可能になります。

バージョン管理システムの長い歴史

自動化されたバージョン管理システムは最近発明されたものではありません。 RCSCVSSubversionなどのツールは1980年前半から存在しており、多くの会社に使われていました。 しかし、これらのツールでは出来る事に制限があり、多くはもう時代遅れとされています。 現代使われているシステム、例えばGitやMercurial、は _分散_されています。というのは、特定のサーバーを必要とせずにシステムをホストする事が出来るという事です。 現代のシステムには大変便利で効果的な「merge(マージ)」機能が備われており、同じファイルを 複数人で作業する事が可能になりました。

論文を書くにあたって

  • 例えば、論文のために数百行書いたとします。しばらくして、間違えてその文章を編集してしまいます。 どうしたら以前書いた文章を取り戻すことができるのでしょう? そもそも、可能なのでしょうか?

  • 五人の共著者がいるとします。 どうやって全員の変更やコメントを管理すれば良いのでしょう? LibreOffice WriterやMicrosoft Wordの場合、こういった変更やコメントを変更履歴機能で受け入れると どうなるのでしょう? 変更点は記録されるのでしょうか?

  • 以前書いた数百行の回復は、古いバージョンの論文のコピーを作成した場合にのみ可能です。 前に書いた文章を失う危険性は、このページの上にある漫画に描かれているような問題のあるワークフローになることが多いです。

  • 従来のワープロを使った共同執筆は面倒です。 すべての共同作業者が文書に順番に書く(執筆のプロセスを遅らせる)か、一つのバージョンをすべての全員に送り、手作業で彼らのコメントをあなたの文書にマージしなければなりません。 「変更の追跡」または「変更の記録」オプションは、変更をハイライトし、マージを簡略化することができますが、変更を受け入れるとすぐにその履歴が失われます。 そうなると、誰がその変更を提案したのか、なぜそれが提案されたのか、いつ文書にマージされたのか、わからなくなります。 Google DocsやMicrosoft Office Onlineのようなオンライン・ワープロでさえ、こうした問題を完全に解決することはできません。

まとめ

  • バージョン管理とは、制限無く「元に戻す」ことができる機能。
  • バージョン管理を使えば、複数の人と同時進行で作業をする事ができます。

Content from Gitの設定


最終更新日:2024-03-28 | ページの編集

概要

質問

  • Git を使うために必要な設定は何ですか?

目的

  • コンピュータで初めて git を使うための設定が出来るようになりましょう。
  • --global 設定フラグの意味を理解しましょう。

Git を新しいパソコンで初めて使う場合、いくつかの設定を変更しなければなりません。 Git を始めるにあたって、私達が変更する設定をいくつか表記します:

  • 名前とメールアドレス、
  • 使用したいテキストエディタ、
  • 以上の設定をグローバル設定として使う(つまり、全てのプロジェクトに反映させる)。

コマンドラインでは、Git コマンドは git <動詞> <オプション> と入力します。ここでの「動詞」は、Git に何をさせたいのかを表し、「オプション」はその動詞にとって必要とされる追加の情報です。 ドラキュラが新しいユーザーの場合、以下のようにコンピュータを設定します:

BASH

Vim の終了の仕方

ここでは、ドラキュラの代わりに自分の名前とメールアドレスを使いましょう。 ここで入力した名前とメールアドレスは、これから行う Git での作業に関わってきます。というのも、これからのレッスンでGitHubBitBucketGitLab、またはその他のGit をホストするサーバーに変更箇所を「プシュ」した(送った)際に、これらの情報が使われるからです。

これらのレッスンでは、GitHub に接続するので、GitHub アカウントと同じメールアドレスに設定してください。 プライバシーについて気になる方は、GitHub のメールアドレスをプライベートにするための説明 を参照してください。

電子メールの非公開

GitHub でプライベートのメールアドレスを使う場合は、同じメールアドレスを user.email の値に設定してください(例:username@users.noreply.github.com)。

改行コード

他のキーと同様に、キーボードで Enter または (またはMacでは Return)を押すと、コンピュータはそれを文字として入力します。 話が長くなるので詳しい説明は省きますが、行末に使われる文字はオペレーティングシステム(OS)よって違います。 (行末に使われる文字を「改行コード」と呼びます。) Git は、改行コードを使ってファイルの違いを確かめるため、違うパソコンでファイルを編集した時に思わぬ問題が起こるかもしれません。 このレッスンの範囲外ですが、この問題については Pro Git book を読んでください。

Git がどのように改行コードを理解・変換するかは、 git configcore.autocrlf コマンドを使って変更できます。 以下の設定をおすすめします:

macOS および Linux:

BASH

$ git config --global core.autocrlf input

またはWindowsの場合:

BASH

$ git config --global core.autocrlf true

以下の表を参考に、ドラキュラはテキストエディタも設定しました:

エディタ 設定コマンド
Atom $ git config --global core.editor "atom --wait"
nano $ git config --global core.editor "nano -w"
BBEdit(Mac、コマンドラインツール付き) $ git config --global core.editor "bbedit -w"
Sublime Text (Mac) $ git config --global core.editor "/Applications/Sublime\ Text.app/Contents/SharedSupport/bin/subl -n -w"
Sublime Text (Win、32ビットインストール) $ git config --global core.editor "'c:/program files (x86)/sublime text 3/sublime_text.exe' -w"
Sublime Text (Win、64ビットインストール) $ git config --global core.editor "'c:/program files/sublime text 3/sublime_text.exe' -w"
メモ帳(Win) $ git config --global core.editor "c:/Windows/System32/notepad.exe"
Notepad++ (Win、 32 ビットインストール) $ git config --global core.editor "'c:/program files (x86)/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin"
Notepad++ (Win、 64 ビットインストール) $ git config --global core.editor "'c:/program files/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin"
Kate (Linux) $ git config --global core.editor "kate"
Gedit (Linux) $ git config --global core.editor "gedit --wait --new-window"
Scratch (Linux) $ git config --global core.editor "scratch-text-editor"
Emacs $ git config --global core.editor "emacs"
Vim $ git config --global core.editor "vim"
VS Code $ git config --global core.editor "code --wait"

設定したテキストエディタもいつでも変更することができます。

Vim の終了の仕方

多くのソフトの初期設定では、Vim がデフォルトのテキストエディタに設定されています。 保存せずに Vim を終了するには、Escを押した後に :q! と入力してからEnterまたは(Macの場合はReturn)を押してください。 保存してから終了するには、Escを押してから :wq と入力してEnterまたは(Mac の場合は Return)を押してください。

Git (2.28以上) では、新しいリポジトリを初期化したときに作成されるブランチの名前を設定できます。 ドラキュラはその機能を使って、最終的に使うクラウドサービスと一致するようにmainに設定することにします。

BASH

$ git config --global init.defaultBranch main

Gitブランチ名の設定

ソースファイルのどんな変更でも、ある「ブランチ」に属しています。 このレッスンの新しい学習者にとっては、ブランチが存在し、このレッスンでは1つのブランチを使うことを知っていれば十分です。
デフォルトでは、git init で新しいリポジトリを作成すると、Git がmaster というブランチを作成します (次のエピソードで説明します)。 この用語は、 人身売買という人種差別的慣習を想起させ、 ソフトウェア開発コミュニティ は、 より包括的な言葉を採用するように動いています。

2020年には、ほとんどのGit ホスティングサービスは、mainをデフォルトの ブランチとして使うように移行しました。 例として、GitHub やGitLab で新規に開いたリポジトリのデフォルトは mainです。 しかし、Gitはまだ同じ変更を行っていません。 その結果、ローカル・リポジトリは、ほとんどのクラウド・サービスと同じブランチ名を手動で設定する必要があります。

2.28より前のバージョンのGitでは、個々のリポジトリで変更が可能です。 そのためのコマンドは次回のエピソードで紹介します。 ローカルのGit の設定でこの値が設定されていない場合、init.defaultBranch のデフォルト値は master になることに注意しましょう。

上記の5つのコマンドは、一度実行するだけで十分です。--global フラグは Git に、 今使っているパソコン内にある自分のアカウントに関連する全てのプロジェクトに同じ設定をするように指示しています。

さっそくこれらの設定を確認し、core.editorをテストしてみましょう:

BASH

$ git config --global --edit

追加の変更を加えずにファイルを閉じましょう。 設定ファイルのタイプミスは問題を引き起こすため、以下のように設定を表示する方が安全です。

BASH

$ git config --list

また、必要であれば、同じコマンドを使えば、違うエディタやメールアドレスに変えることができます。 これは何度でもできます。

プロキシ

ネットワーク環境によってはプロキシ を使わなければならないかもしれません。 この場合、プロキシの設定が必要です:

BASH

$ git config --global http.proxy proxy-url
$ git config --global https.proxy proxy-url

プロキシを無効にするには:

BASH

$ git config --global --unset http.proxy
$ git config --global --unset https.proxy

Git のヘルプとマニュアル

git のコマンドを忘れた時は、-h を使えばコマンドの一覧を、--help を使えばマニュアルを見ることができます:ある git コマンドのサブコマンドやオプションを忘れてしまった場合は、 git <command> -h とタイプすることによって関連するオプションのリストを見るか、git <command> --help とタイプすることによって対応する Git マニュアルを見ることができます:

BASH

$ git config -h
$ git config --help

マニュアルを見ている間、:はコマンドを待っているプロンプトであり、 Q を押してマニュアルを終了できることを覚えておいてください。

より一般的には、利用可能な git コマンドのリストや、Git マニュアルを入手することができます:

BASH

$ git help

まとめ

  • git config--global オプションを使い、ユーザー名、メールアドレス、エディタ、その他の設定を行う。

Content from リポジトリの作成


最終更新日:2024-03-28 | ページの編集

概要

質問

  • Gitはどこに情報を格納しますか?

目的

  • ローカルのGitリポジトリを作成する。
  • .git ディレクトリの目的を説明する。

Gitの設定ができたら、 それを使い始めることができます。

火星に惑星着陸船を送ることが可能かどうかを調査しているウルフマンとドラキュラの話に戻りましょう。

motivatingexampleウルフマン対ドラキュラ by b-maze / Deviant Art. 火星 by European Space Agency / CC-BY-SA 3.0 IGO. 冥王星 / Courtesy NASA/JPL-Caltech. ミイラ © Gilad Fried / The Noun Project / CC BY 3.0. © Luc Viatour / https://lucnix.be / CC BY-SA 3.0.

まず、Desktopフォルダーに作業用のディレクトリを作成し、そのディレクトリに移動しましょう:

BASH

$ cd ~/Desktop
$ mkdir planets
$ cd planets

次に、Gitにplanetsリポジトリ(Gitがファイルのバージョンを保存できる場所)にするように伝えます。

BASH

$ git init

重要なのは、git init はサブディレクトリとそのファイルを含むことができるリポジトリを作成するということです。サブディレクトリが最初から存在する場合でも、後から追加された場合でも、planets リポジトリの中に入れ子になった別のリポジトリを作成する必要はありません。 また、 planetsディレクトリの作成と、リポジトリとしての初期化はまったく別の処理であることに注意してください。

ls を使ってディレクトリの内容を表示すると、 何も変更されていないように見えます:

BASH

$ ls

ですが -a フラグを追加してすべてを表示すると、Git が .gitという隠しディレクトリを planets の中に作ったことがわかります:

BASH

$ ls -a

出力

.	..	.git

Git はプロジェクトのディレクトリ内にあるすべてのファイルとサブディレクトリを含む、プロジェクトに関するすべての情報を格納するためにこの特別なサブディレクトリを使用します。 .git サブディレクトリを削除すると、プロジェクトの履歴を失うことになります。

次に、デフォルトのブランチを main という名前に変更します。 あなたの設定やgitのバージョンによっては、これが既にデフォルトになっているかもしれません。 この変更の詳細については、「セットアップ」 を参照してください。

BASH

$ git checkout -b main

出力

Switched to a new branch 'main'

プロジェクトのステータスをGitに問うことで、すべてが正しく設定されていることを確認できます:

BASH

$ git status

出力

On branch main

No commits yet

nothing to commit (create/copy files and use "git add" to track)

使用しているgitのバージョンによって、出力の表現が少し異なるかもしれません。

Git リポジトリを作る場所

planets (すでに作成したプロジェクト)についての情報を追跡すると共に、 ドラキュラは moons についての情報も追跡したいと考えています。 ウルフマンの心配にもかかわらず、ドラキュラは次の一連のコマンドを使って、彼の planetsプロジェクト内に moons プロジェクトを作ります:

BASH

$ cd ~/Desktop   # Desktop ディレクトリに戻る
$ cd planets     # すでに Git リポジトリである planets ディレクトリに移動する
$ ls -a          # .git サブディレクトリがまだ planets ディレクトリに存在することを確認する
$ mkdir moons    # サブディレクトリ planets/moons を作る
$ cd moons       # moons サブディレクトリに移動する
$ git init       # moons サブディレクトリをGitリポジトリにする
$ ls -a          # .git サブディレクトリが存在し新しいGitリポジトリが作られたと示していることを確認する

git init コマンドは、moons サブディレクトリ内で実行され、moons サブディレクトリに保存されているファイルを追跡するために必要でしょうか?

いいえ。 ドラキュラは moons サブディレクトリを Git リポジトリにする必要はありません。planets リポジトリは、planets ディレクトリの下のすべてのファイル、サブディレクトリ、およびサブディレクトリファイルを追跡するからです。 従って、moons についてのすべての情報を追跡するのは、ドラキュラが moons サブディレクトリをplanets ディレクトリに追加するだけで済みます。

それと、Git リポジトリが「入れ子」にされている場合、Gitリポジトリは互いに干渉する可能性があります:外側のリポジトリは内側のリポジトリのバージョン管理をしようとします。 したがって、新しいGitリポジトリはそれぞれ別のディレクトリに作るのがベストです。 ディレクトリに競合するリポジトリががないことを確認するには、git statusの出力を確認します。 次のような場合は、上の方で示したように新しいリポジトリを作ることをお勧めします:

BASH

$ git status

出力

fatal: Not a git repository (or any of the parent directories): .git

git initの間違いを修正する

ウルフマンはドラキュラに、「入れ子」状態になっているリポジトリがいかに冗長で、混乱を引き起こす可能性があるかを説明しました。 説明を聞いて、ドラキュラは「入れ子」状態のリポジトリを削除したいと思いました。 moonsサブディレクトリの最後のgit initを、ドラキュラはどうやって、元に戻すことができるのでしょうか?

背景

Gitリポジトリからのファイルの削除は、慎重に行う必要があります。 しかし、特定のファイルを追跡するようにGitに指示する方法については、まだ学んでいません(次のエピソードで学びます)。 Gitによって追跡されていないファイルは、他の「普通の」ファイルと同じように、次のようにして簡単に削除できます:

BASH

$ rm filename

同様に、rm -r dirname または rm -rf dirname を使ってディレクトリを削除することができます。 この方法で削除されるファイルやフォルダがGitによって追跡されているなら、次のエピソードで見られるように、それらの削除が、追跡する必要がある別の変更になります。

解答

Gitはすべてのファイルを.gitディレクトリに保存します。 この小さなミスから立ち直るには、ドラキュラはplanetsディレクトリの中から次のコマンドを実行して、moonsサブディレクトリの中の.gitフォルダを削除すれば良い:

BASH

$ rm -rf moons/.git

しかし、気をつけてください! 間違ったディレクトリでこのコマンドを実行すると、残しておきたいプロジェクトのGit履歴がすべて削除されてしまいます。 したがって、常に pwd コマンドを使用してカレントディレクトリを確認してください。

まとめ

  • git init はリポジトリを初期化する。
  • Gitはリポジトリデータのすべてを.gitディレクトリに格納する。

Content from 変更内容の記録


最終更新日:2024-03-28 | ページの編集

概要

質問

  • どうやって変更点を Git で記録出来ますか?
  • どうやってリポジトリの状態をチェック出来ますか?
  • 何を変更して、なぜ変えたのかをメモするにはどうすればよいですか?

目的

  • 一つ以上のファイルにおいて、「変更・追加・コミット」の作業を行いましょう。
  • 「変更・追加・コミット」を行っている際、情報がどこに保管されているのか説明しましょう。
  • わかりやすいコミットメッセージと、そうでないメッセージの違いを区別できるようになりましょう。

まずはじめに、正しいディレクトリにいるかどうか確かめましょう。 planets ディレクトリに入っているはずです。

BASH

$ cd ~/Desktop/planets

赤い惑星(火星)が基地に最適かどうかについてのノートを書くためにmars.txt というファイルを作成しましょう。 nano (もしくは好きなテキストエディタ)でファイルを編集しましょう。 以前 core.editor で設定したエディタとは別のエディタで編集しても大丈夫です。 ですが、新しくファイルを作成・編集するコマンドはエディタによって違うということを覚えておいてください(nano ではないかもしれません)。 テキストエディタについて復習したい方は、Unix シェルどのエディタ? のレッスンを見てみてください。

BASH

$ nano mars.txt

以下の文を mars.txt に記入してください:

出力

Cold and dry, but everything is my favorite color

まず、listコマンド(ls)を実行して、ファイルが正しく作成されたことを確認しましょう:

BASH

$ ls

出力

mars.txt

これで mars.txt は一文だけ入ってる状態になりました。確認してみましょう:

BASH

$ cat mars.txt

出力

Cold and dry, but everything is my favorite color

プロジェクトの状態をもう一度確認してみると、 Git は新しいファイルがあることに気づきます:

BASH

$ git status

出力

On branch main

No commits yet

Untracked files:
   (use "git add <file>..." to include in what will be committed)

	mars.txt

nothing added to commit but untracked files present (use "git add" to track)

“untracked files” (追跡されていないファイル)というメッセージは、 Git が追跡していないファイルがこのディレクトリに存在していることを意味します。 git add を使って、Git にこのファイルを追跡してもらいましょう: git add を使って、Git にこのファイルを追跡してもらいましょう:

BASH

$ git add mars.txt

そして、正しく動作したか確認してみましょう:

BASH

$ git status

出力

On branch main

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

	new file:   mars.txt

これで Git は mars.txt を追跡するように設定することができました。 ですが、まだ変更点をコミットとして記録していません。 これをするには、もう一つコマンドを使う必要があります:

BASH

$ git commit -m "Start notes on Mars as a base"

出力

[main (root-commit) f22b25e] Start notes on Mars as a base
 1 file changed, 1 insertion(+)
 create mode 100644 mars.txt

git commit を使うと、 Git は git add によって一時的に保存されたデータを .git ディレクトリにコピー、そして永久保存します。 永久保存されたコピーを コミット (または リビジョン))と呼び、f22b25e はコミットの省略されたIDです。 あなたのコミットには別のIDが使われているかもしれません。

-m フラグ(「メッセージ」の略)を使い、何を変えて、なぜ変えたのかが後からでも分かるように、簡潔で分かりやすいメッセージを書きましょう。 -m を使わずに git commit を使った場合、Git は nano (または core.editor として設定したエディタ)を開き、もっと長いメッセージを書くことができます。

良いコミットメッセージ は、どのような変更が行われたのかが分かる短い文(50字以下) で始まります。 大抵のメッセージは、「このコミットを適用すると」という文が完全文になるように書かれます。 もっと詳しく書きたい場合は、このメッセージの後に改行してからノートを加えましょう。 ここには、なぜこのような変更をしたのか、この変更によって何が影響を受けるかなどといった事を書くといいでしょう。

今の状態で git status を走らせると:

BASH

$ git status

出力

On branch main
nothing to commit, working tree clean

といったように、最新の状態であることを教えてくれます。 つい先程、何をしたのかを見たい場合は git log を使って、 Git にプロジェクトの履歴を表示してもらいましょう:

BASH

$ git log

出力

commit f22b25e3233b4645dabd0d81e651fe074bd8e73b
Author: Vlad Dracula <vlad@tran.sylvan.ia>
Date:   Thu Aug 22 09:51:46 2013 -0400

    Start notes on Mars as a base

git log は、リポジトリに施された全てのコミットを最新のものから順に表示します。 各コミットには、省略されていないコミットID(以前 git commit で表示された省略IDと同じ字列で始まります)、コミットの著者、作成日時、そして、コミットが作られた時につけられたログメッセージが含まれています。

変更点は何処にあるの?

ここで ls を使用すると、mars.txt ファイル一つしかありません。 なぜかと言うと、Git はファイルの変更履歴を、以前触れた .git という特別なディレクトリに保存します。これをする事によって、ファイルシステムが散らからないようにし、うっかり古いバージョンのファイルを変更、または削除できないようにしています。

それでは、ドラキュラがファイルに新しい情報を加えたとしましょう。 (以前と同様に、nano を使い、cat でファイルの中身を表示させます。違うエディタを使ってもいいし、cat を使わなくても構いません。)

BASH

$ nano mars.txt
$ cat mars.txt

出力

Cold and dry, but everything is my favorite color
The two moons may be a problem for Wolfman

git status を使うと、追跡しているファイルが変更されたことを知らせてくれます:

BASH

$ git status

出力

On branch main
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:   mars.txt

no changes added to commit (use "git add" and/or "git commit -a")

最後に表示された文が一番重要です:“no changes added to commit” (「変更点はコミットに追加されていません」)。 私達はファイルを編集したのですが、まだ Git にこの変更点を保存したいということを(git add で)伝えていないし、それを(git commit で)保存もしていません。 というわけで、これらをやってみましょう。 変更点を保存する前に見直すのは、習慣づけると良いでしょう。 見直すには git diff を使いましょう。 これによって、今のファイルの状態と、一つ前までのファイルの状態との違いを確かめることができます:

BASH

$ git diff

出力

diff --git a/mars.txt b/mars.txt
index df0654a..315bf3a 100644
--- a/mars.txt
+++ b/mars.txt
@@ -1 +1,2 @@
 Cold and dry, but everything is my favorite color
+The two moons may be a problem for Wolfman

すると、暗号のようなメッセージが出力されます。 これらのメッセージは、エディタや patch といったプログラムで使われる 一連のコマンドで、ファイルをどうやって再構成するのかが書かれています。 分かりやすいように、一文ずつ見てみましょう:

  1. 最初の文は、Git が古いバージョンと新しいバージョンのファイルをUnix のdiffコマンドと同じように、二つのファイルを比べていることを表しています。
  2. 次に、Git が比べているファイルの正確なバージョンを表示しています。df0654a315bf3a はコンピュータが作成した、各バージョン”につけられたIDです。
  3. 3・4つ目の文章は、変更されているファイルの名前を表示しています。
  4. 残りの文章が一番重要です。ここに、何が変わり、どの行が変更されたのかが記されています。 特に、この+ マークは、どこに文章が加えられたのかを表しています。

変更点を確認したら、コミットしましょう:

BASH

$ git commit -m "Add concerns about effects of Mars' moons on Wolfman"

出力

On branch main
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:   mars.txt

no changes added to commit (use "git add" and/or "git commit -a")

おっと、 初めに git add を使わなかったので、 Git はコミットさせてくれませんでした。 直しましょう: Let’s fix that:

BASH

$ git add mars.txt
$ git commit -m "Add concerns about effects of Mars' moons on Wolfman"

出力

[main 34961b1] Add concerns about effects of Mars' moons on Wolfman
 1 file changed, 1 insertion(+)

Git は変更をコミットする前に、コミットしたいファイルを 追加するように要求してきます。 これによって、変更点をこまめに、そして論理的に分割して保存ができ、大きな変更をひとまとめに保存しなくてもよくなります。 例えば、論文にいくつか引用源を加えるとします。 これらの引用源、そして使われた参考文献の目録を、まだ書き終わっていない結論とは_別に_保存したい場合はどうすればいいのでしょう。

Git には、まだコミットされていないchangeset(一連の変更点)を一時的に保存・把握するために使われる、staging area(ステージング・エリア)と呼ばれる特殊な場所が存在します。

ステージングエリア

仮にGit を、プロジェクトの一生の間に起こった変更内容を「スナップショット」として保存するものとして考えると、git add は_何が_スナップショットに含まれる(ステージングエリアに入れる)のかを指定して、git commit は_実際にスナップショットを撮り_、コミットとして永久保存します。 git commit と入力した際にステージングエリアに何もなかった場合、Git はgit commit -a もしくは git commit --all を入力するように言ってきます。このコマンドは、写真を撮る時の「全員集合!」のようなもので、全ての変更点を強制的にコミットできます。 ですが、大抵は、コミットしたい変更点のみをステージングエリアに入れるほうが良いでしょう。これによって、不要な変更点を間違えてコミットすることもありません。 (集合写真の例に例えると、メイクの不完全なエキストラがステージの上を横断しているのを一緒に撮ってしまった、みたいなものです。) ですので、ステージングエリアにどの変更点を入れるかは自分で管理しましょう。さもないと、必要以上に「git コミットやり直す」で検索をかけることになるでしょう。

The Git Staging Area

それでは、ファイルの変更点がエディタからステージングエリア、そして長期保存に移る過程を見てみましょう。 初めに、新しい文章をファイルに加えましょう:

BASH

$ nano mars.txt
$ cat mars.txt

出力

Cold and dry, but everything is my favorite color
The two moons may be a problem for Wolfman
But the Mummy will appreciate the lack of humidity

BASH

$ git diff

出力

diff --git a/mars.txt b/mars.txt
index 315bf3a..b36abfd 100644
--- a/mars.txt
+++ b/mars.txt
@@ -1,2 +1,3 @@
 Cold and dry, but everything is my favorite color
 The two moons may be a problem for Wolfman
+But the Mummy will appreciate the lack of humidity

いい感じです。 これでファイルの最後に新しく文章を足すことができました。 (左にある + マークで記されています。) それでは変更点をステージングエリアに入れて git diff がなにを表示するのかを見てみましょう:

BASH

$ git add mars.txt
$ git diff

何も表示されませんでした。Git が見た限りでは、保存したい変更点と今ディレクトリ内にあるファイルには、これといった違いは無いということになります。 ですが、こう入力すると:

BASH

$ git diff --staged

出力

diff --git a/mars.txt b/mars.txt
index 315bf3a..b36abfd 100644
--- a/mars.txt
+++ b/mars.txt
@@ -1,2 +1,3 @@
 Cold and dry, but everything is my favorite color
 The two moons may be a problem for Wolfman
+But the Mummy will appreciate the lack of humidity

以前コミットされた状態のファイルとステージングエリアにある変更点の違いが表示されます。 変更内容を保存しましょう:

BASH

$ git commit -m "Discuss concerns about Mars' climate for Mummy"

出力

[main 005937f] Discuss concerns about Mars' climate for Mummy
 1 file changed, 1 insertion(+)

状態をチェックしましょう:

BASH

$ git status

出力

On branch main
nothing to commit, working tree clean

そして、今までの変更履歴も見てみましょう:

BASH

$ git log

出力

commit 005937fbe2a98fb83f0ade869025dc2636b4dad5 (HEAD -> main)
Author: Vlad Dracula <vlad@tran.sylvan.ia>
Date:   Thu Aug 22 10:14:07 2013 -0400

    Discuss concerns about Mars' climate for Mummy

commit 34961b159c27df3b475cfe4415d94a6d1fcd064d
Author: Vlad Dracula <vlad@tran.sylvan.ia>
Date:   Thu Aug 22 10:07:21 2013 -0400

    Add concerns about effects of Mars' moons on Wolfman

commit f22b25e3233b4645dabd0d81e651fe074bd8e73b
Author: Vlad Dracula <vlad@tran.sylvan.ia>
Date:   Thu Aug 22 09:51:46 2013 -0400

    Start notes on Mars as a base

文字ごとの違いを表示する

時折、例えばテキストドキュメントなど、列ごとの違いを表示するのは大雑把すぎる場合があります。 こういう時は、git diff--color-words オプションを使えば、色で文字ごとの違いを表示してくれるので、大変便利です。

ログをめくる

git log の出力がスクリーンよりも長いと、git はスクリーンに収まるようにログを分割して表示するプログラムを使います。 この “pager” (ページャ)というプログラムが開くと、一番下の列がプロンプトではなく、: になります。

  • ページャを閉じるには Q を押してください。
  • 次のページを表示するには Spacebarを押してください。
  • ある <文字> を全ページの中から検索する時は、/ を押し、<文字> を入力してください。 Nを押すと次の一致場所に行けます。

ログの出力を制限する

git log の出力がスクリーン全体を埋めないようにするために、Gitが表示するコミットの数を -N で変えることができます。この Nは、表示したいコミットの数を表しています。 例えば、最新のコミットの情報だけを表示したい場合は、こう入力します:

BASH

$ git log -1

出力

commit 005937fbe2a98fb83f0ade869025dc2636b4dad5 (HEAD -> main)
Author: Vlad Dracula <vlad@tran.sylvan.ia>
Date:   Thu Aug 22 10:14:07 2013 -0400

   Discuss concerns about Mars' climate for Mummy

--oneline オプションを使うことによって、表示する情報を制限する事ができます:

BASH

$ git log --oneline

出力

005937f (HEAD -> main) Discuss concerns about Mars' climate for Mummy
34961b1 Add concerns about effects of Mars' moons on Wolfman
f22b25e Start notes on Mars as a base

--oneline オプションを他のオプションと組み合わせることもできます。 便利な組み合わせの一つとして、 --graph を追加すると、コミット履歴をテキストベースのグラフとして表示し、どのコミットが現在の HEAD、現在のブランチ main、あるいはその他の Git リファレンスに関連しているかを示すことができます:

BASH

$ git log --oneline --graph

出力

* 005937f (HEAD -> main) Discuss concerns about Mars' climate for Mummy
* 34961b1 Add concerns about effects of Mars' moons on Wolfman
* f22b25e Start notes on Mars as a base

ディレクトリ

Git でディレクトリを使用する際は、以下の二点を覚えておきましょう。

  1. Git はディレクトリ単体を追跡することはなく、ディレクトリ内のファイルのみを追跡します。 自分で試してみてください:

BASH

$ mkdir spaceships
$ git status
$ git add spaceships
$ git status

注目してほしいのは、新しく作った directory ディレクトリは git add でリポジトリに追加したにも関わらず、追跡されてないファイルのリストに表示されていません。 たまに .gitkeep ファイルが空のディレクトリ内にあるのは、このためです。 .gitignoreとは違って、このファイルは特別でも何でもなく、空のディレクトリを Git のリポジトリに追加、そして追跡させるためだけに置いてあるだけです。 なので、別の名前のファイルでも同じことができます。

  1. Git リポジトリ内でディレクトリを作成し、複数のファイルをそのディレクトリに入れたい場合、ディレクトリ内のファイルをひとまとめに追加する事ができます:

BASH

git add <directory-with-files>

自分で試してみてください:

BASH

$ touch spaceships/apollo-11 spaceships/sputnik-1
$ git status
$ git add spaceships
$ git status

次に進む前に、これらの変更をコミットしましょう。

BASH

$ git commit -m "Add some initial thoughts on spaceships"

まとめると、変更内容をリポジトリに追加したい時はgit add で変更点をステージングエリアに移してから、git commit でステージングエリアの変更点をリポジトリに保存します:

The Git Commit Workflow

コミットメッセージを決める

以下のコミットメッセージの内、最後の mars.txt のコミットに最適なメッセージはどれでしょう?

  1. “Changes”
  2. “Added line ‘But the Mummy will appreciate the lack of humidity’ to mars.txt”
  3. “Discuss effects of Mars’ climate on the Mummy”

1つ目のメッセージは短すぎてコミットの内容が何なのかわかりにくいです。2つ目はgit diffで何が変わったのかが分かるので、長い割にはあまり意味がありません。3つ目は、短く、簡潔で、分かりやすいメッセージです。

Git に変更点をコミットする

以下の内、myfile.txt を Git リポジトリに保存するためのコマンドはどれでしょう?

  1. BASH

$ git commit -m “my recent changes”

2. ```bash
$ git init myfile.txt
$ git commit -m "my recent changes"
  1. BASH

$ git add myfile.txt $ git commit -m “my recent changes”

4. ```bash
$ git commit -m myfile.txt "my recent changes"
  1. ファイルがステージングエリアにない限り、コミットできません。

  2. 新しくリポジトリを作ろうとします。

  3. 正しい回答です。まずファイルをステージングエリアに追加し、それからコミットします。

  4. “my recent changes” というファイルを myfile.txt というメッセージでコミットしようとします。

複数のファイルをコミットする

一つのコミットに対し、ステージングエリアは複数のファイルの変更点を保持する事ができます。

  1. mars.txt に、火星ではなく金星に基地を作ることにしたという文章を加えましょう。
  2. 新しく venus.txt というファイルを作り、金星に基地を置く決断についての感想を書きましょう。
  3. 二つのファイルの変更内容をステージングエリアに加えて、コミットしましょう。

以下のcat mars.txtの出力は、この課題で追加された内容のみを反映しています。 出力は異なる場合があります。

まずは mars.txtvenus.txt を編集しましょう:

BASH

$ nano mars.txt
$ cat mars.txt

出力

Maybe I should start with a base on Venus.

BASH

$ nano venus.txt
$ cat venus.txt

出力

Venus is a nice planet and I definitely should consider it as a base.

これで二つのファイルをステージングエリアに追加することができます。 二つのファイルを一気に追加するには:

BASH

$ git add mars.txt venus.txt

一つずつ追加するには:

BASH

$ git add mars.txt
$ git add venus.txt

これでファイルをコミットする準備ができました。 git status でチェックしましょう。 コミットをするには:

BASH

$ git commit -m "Write plans to start a base on Venus"

出力

[main cc127c2]
 Write plans to start a base on Venus
 2 files changed, 2 insertions(+)
 create mode 100644 venus.txt

bioリポジトリ

  • bio という Git リポジトリ新しく作りましょう。
  • me.txt というファイルに自分について3文書いて、変更点をコミットしてください。
  • すでに書いた文章の内、ひとつだけ編集して、更にもう一文加えてください。
  • 編集した後の状態とその前の違いを表示してください。

必要であれば、planets から出ましょう:

BASH

$ cd ..

新しく bio というディレクトリを作り、中に移動しましょう:

BASH

$ mkdir bio
$ cd bio

リポジトリを作りましょう:

BASH

$ git init

nano か他のテキストエディタで me.txt を作りましょう。 作ったら、変更点を追加してコミットしてください:

BASH

$ git add me.txt
$ git commit -m "Add biography file" 

指示通りにファイルを編集してください(一文だけ変えて、もう一文足す)。 オリジナルと編集後のファイルの違いを表示させるために、git diff を使います:

BASH

$ git diff me.txt

まとめ

  • git status はリポジトリの状態を表示する。
  • ファイルはプロジェクトの作業ディレクトリ、ステージング・エリア(次のコミットに含まれる変更点が蓄積される場所)、そしてローカル・リポジトリ(コミットが永久に記録される場所)に保存される。
  • git add はファイルをステージング・エリアに移動させる。
  • git commit はステージされた内容をローカル・リポジトリに保存する。
  • コミットメッセージは、変更点がわかりやすいように書きましょう。

Content from 履歴の探索


最終更新日:2024-02-25 | ページの編集

概要

質問

  • ファイルの古いバージョンを復元するにはどうすればよいでしょうか?
  • 変更内容を再調査するにはどうすればよいでしょうか?
  • ファイルの古いバージョンを復元するにはどうすればよいでしょうか?

目的

  • リポジトリのHEADとは何か、またその使い方を説明出来るようになりましょう。
  • Gitのコミット番号を特定して使ってみましょう。
  • 追跡調査されるファイルのいろいろなバージョンを比較してみましょう。
  • ファイルの古いバージョンを復元してみましょう。

前のレッスンで見たように、コミットを識別子で参照できます。 識別子 HEAD を使うことで作業ディレクトリの 最新のコミット を参照できます。

mars.txt に一度に1行ずつ追加しているので、進展を見て確認することは簡単です。それでは HEAD を使ってそれを行ってみましょう。 始める前に、 mars.txt にもう1行加えることで変更を加えてみましょう。

BASH

$ nano mars.txt
$ cat mars.txt

出力

Cold and dry, but everything is my favorite color
The two moons may be a problem for Wolfman
But the Mummy will appreciate the lack of humidity
An ill-considered change

それでは、何が得られるか見てみましょう。

BASH

$ git diff HEAD mars.txt

出力

diff --git a/mars.txt b/mars.txt
index b36abfd..0848c8d 100644
--- a/mars.txt
+++ b/mars.txt
@@ -1,3 +1,4 @@
 Cold and dry, but everything is my favorite color
 The two moons may be a problem for Wolfman
 But the Mummy will appreciate the lack of humidity
+An ill-considered change.

これは、 HEAD を省略した場合 (試してみてください) に得られるものと同じです。 これの本当の利点は、以前のコミットを参照できることです。 それを行うには、HEAD より前のコミットを参照するために ~1 (「~」は「チルダ」、発音は [til-d_uh_]) を追加します。

BASH

$ git diff HEAD~1 mars.txt

古いコミット間の違いを確認したい場合は、git diff を再度使用できますが、HEAD~1HEAD~2 などの表記を使用して、それらを参照するには下記を行います:

BASH

$ git diff HEAD~3 mars.txt

出力

diff --git a/mars.txt b/mars.txt
index df0654a..b36abfd 100644
--- a/mars.txt
+++ b/mars.txt
@@ -1 +1,4 @@
 Cold and dry, but everything is my favorite color
+The two moons may be a problem for Wolfman
+But the Mummy will appreciate the lack of humidity
+An ill-considered change

git diff を使用して表示されるコミットと作業ディレクトリの 違い ではなく、古いコミットで行った変更だけでなくコミットメッセージも表示する git showを使用することもできます。

BASH

$ git show HEAD~3 mars.txt

出力

commit f22b25e3233b4645dabd0d81e651fe074bd8e73b
Author: Vlad Dracula <vlad@tran.sylvan.ia>
Date:   Thu Aug 22 09:51:46 2013 -0400

    Start notes on Mars as a base

diff --git a/mars.txt b/mars.txt
new file mode 100644
index 0000000..df0654a
--- /dev/null
+++ b/mars.txt
@@ -0,0 +1 @@
+Cold and dry, but everything is my favorite color

このようにして、コミットのチェーンを構築できます。 チェーンの最新の終わりは HEAD と呼ばれます; ~ 表記を使用して以前のコミットを参照できるため、HEAD~1 は「以前のコミット」を意味し、HEAD~123 は現在の場所から123個前のコミットに戻ります。

git log が表示する、数字と文字の長い文字列を使用してコミットを参照することもできます。 これらは一個一個の変更に対するユニークなIDであり、「ユニーク」は本当に唯一であることを意味します: どのコンピューターのどのファイルの変更の組み合わせに対しても、ユニークな40文字の ID があります。 最初のコミットにはID f22b25e3233b4645dabd0d81e651fe074bd8e73b が与えられたので、これを試してみましょう:

BASH

$ git diff f22b25e3233b4645dabd0d81e651fe074bd8e73b mars.txt

出力

diff --git a/mars.txt b/mars.txt
index df0654a..93a3e13 100644
--- a/mars.txt
+++ b/mars.txt
@@ -1 +1,4 @@
 Cold and dry, but everything is my favorite color
+The two moons may be a problem for Wolfman
+But the Mummy will appreciate the lack of humidity
+An ill-considered change

これは正しい答えですが、ランダムな40文字の文字列を入力するのは面倒なので、Gitは最初の数文字だけを使えばよいようにしてくれています:

BASH

$ git diff f22b25e mars.txt

出力

diff --git a/mars.txt b/mars.txt
index df0654a..93a3e13 100644
--- a/mars.txt
+++ b/mars.txt
@@ -1 +1,4 @@
 Cold and dry, but everything is my favorite color
+The two moons may be a problem for Wolfman
+But the Mummy will appreciate the lack of humidity
+An ill-considered change

やりました! こんなわけで ファイルへの変更を保存して、何が変更されたかを確認できます。 では、どうすれば古いバージョンのものを復元できるでしょうか? mars.txtへの最後の更新(「熟考を欠いた変更」)について気が変わったとしましょう。

git status は、ファイルが変更されたことを示しますが、それらの変更はステージングされていません:

BASH

$ git status

出力

On branch main
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:   mars.txt

no changes added to commit (use "git add" and/or "git commit -a")

git checkoutを使うと、元の状態に戻すことができます:

BASH

$ git checkout HEAD mars.txt
$ cat mars.txt

出力

Cold and dry, but everything is my favorite color
The two moons may be a problem for Wolfman
But the Mummy will appreciate the lack of humidity

その名前から推測できるように、git checkout はファイルの古いバージョンをチェックアウト (つまり、復元) します。 この場合、最後に保存されたコミットである HEAD に記録されたファイルのバージョン を復元することをGitに伝えています。 さらに戻りたい場合は、代わりにコミット Id を使うことができます:

BASH

$ git checkout f22b25e mars.txt

BASH

$ cat mars.txt

出力

Cold and dry, but everything is my favorite color

BASH

$ git status

出力

On branch main
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   mars.txt

変更はステージング領域にあることに注意してください。 繰り返しますが、git checkout を使うと、元の状態に戻すことができます:

BASH

$ git checkout HEAD mars.txt

HEAD を見失わないようにしましょう

上記では下記を使いました

BASH

$ git checkout f22b25e mars.txt

mars.txt をコミット f22b25e 後の状態に戻すためにです。 しかし、気をつけてください! コマンド checkout には他の重要な機能があり、入力が正確でない場合、Gitはあなたの意図を誤解する可能性があります。 たとえば、前のコマンドで mars.txt を忘れた場合です。

BASH

$ git checkout f22b25e

エラー

Note: checking out 'f22b25e'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

 git checkout -b <new-branch-name>

HEAD is now at f22b25e Start notes on Mars as a base

ここでの「HEADが切り離された」状態は「見れるが触ってはいけない」ようなものなので、この状態で変更を加えないでください。 リポジトリの過去の状態を調査した後、git checkout mainHEADを再接続してください。

取り消したい変更の一個のコミット番号を使う必要があることを覚えておくことが重要です。 よくある間違いは、破棄しようとしている変更を行ったコミットの番号を使用することです。 以下の例では、最新のコミットの前 (HEAD~1) 、すなわちf22b25eから状態を取得したいと考えています:

Git Checkout

つまり、すべてをまとめると、Gitがどのように機能するかは次の漫画のようになります:

https://figshare.com/articles/How\_Git\_works\_a\_cartoon/1328266

よくあるケースの簡単化

git status の出力を注意深く読むと、次のヒントを含んでいることが分かります:

出力

(use "git checkout -- <file>..." to discard changes in working directory)

それが言っているように、バージョン識別子のない git checkout はファイルをHEADに保存された状態に復元します。 二重のダッシュ --はコマンドから復元されるファイルの名前を区別するために必要です:それがないと、Git はファイルの名前をコミット Id として使用しようとします。

ファイルを1つずつ元に戻すことができるという事実は 人々が研究を整理する方法を変えることがあります。 すべての変更が1つの大きなドキュメントに含まれている場合、 後で結論に加えられた変更を元に戻さずに、 序論への変更を元に戻すことは困難です(不可能ではありませんが)。 一方、序論と結論を別々のファイルに保存すると、時間を前後に移動するのがはるかに簡単になります。

ファイルの古いバージョンの復元

ジェニファーは、数週間取り組んできたPythonスクリプトに変更を加えました。そして今朝行った変更により、スクリプトが “壊れ”、動作しなくなりました。 彼女はそれを修正しようとして約1時間費やしましたが、うまく機能しません…

幸い、彼女はGitを使用してプロジェクトのバージョンを追跡していました! 以下のどのコマンドで、data_cruncher.py と呼ばれるPythonスクリプトの最後にコミットされたバージョンを復元できるでしょうか?

  1. $ git checkout HEAD

  2. $ git checkout HEAD data_cruncher.py

  3. $ git checkout HEAD~1 data_cruncher.py

  4. $ git checkout <unique ID of last commit> data_cruncher.py

  5. Both 2 and 4

答えは (5) - 2 と 4 の両方です。

The checkout command restores files from the repository, overwriting the files in your working directory. Answers 2 and 4 both restore the latest version in the repository of the file data_cruncher.py. Answer 2 uses HEAD to indicate the latest, whereas answer 4 uses the unique ID of the last commit, which is what HEAD means.

Answer 3 gets the version of data_cruncher.py from the commit before HEAD, which is NOT what we wanted.

Answer 1 can be dangerous! Without a filename, git checkout will restore all files in the current directory (and all directories below it) to their state at the commit specified. This command will restore data_cruncher.py to the latest commit version, but it will also restore any other files that are changed to that version, erasing any changes you may have made to those files! As discussed above, you are left in a detached HEAD state, and you don’t want to be there.

コミットを戻すことについて

ジェニファーは同僚とPythonスクリプトで共同作業を行っており、グループのリポジトリへの彼女の最新のコミットが間違っていることに気付き、それを元に戻したいと思っています。 ジェニファーは、グループリポジトリのみんなが正しい変更を取得できるように、正しく元に戻す必要があります。 ジェニファーは、グループリポジトリのみんなが正しい変更を取得できるように、正しく元に戻す必要があります。 git revert [wrong commit ID] は、ジェニファーの誤ったコミットを元に戻す新しいコミットを作ります。

従ってgit revertgit checkout [commit ID]とは異なります。なぜなら checkout はグループのリポジトリにはコミットされていないローカルの変更用のコマンドだからです。

以下は、ジェニファーがgit revertを使用するための正しい手順と説明ですが、不足しているコマンドは何でしょうか?

  1. ________ # コミットIDを見つけるために、プロジェクトのgitの 履歴を見ます

  2. そのIDをコピーします (IDの最初の数文字は例えば 0b1d055)。

  3. git revert [commit ID]

  4. 新しいコミットメッセージを入力します。

  5. 保存して閉じます。

The command git log lists project history with commit IDs.

The command git show HEAD shows changes made at the latest commit, and lists the commit ID; however, Jennifer should double-check it is the correct commit, and no one else has committed changes to the repository.

ワークフローと履歴の理解

最後のコマンドの出力は何でしょうか?

BASH

$ cd planets
$ echo "Venus is beautiful and full of love" > venus.txt
$ git add venus.txt
$ echo "Venus is too hot to be suitable as a base" >> venus.txt
$ git commit -m "Comment on Venus as an unsuitable base"
$ git checkout HEAD venus.txt
$ cat venus.txt #this will print the contents of venus.txt to the screen
  1. 出力

Venus is too hot to be suitable as a base

2. ```output
Venus is beautiful and full of love
  1. 出力

Venus is beautiful and full of love Venus is too hot to be suitable as a base

4. ```output
Error because you have changed venus.txt without committing the changes

答えは2です。

The command git add venus.txt places the current version of venus.txt into the staging area. The changes to the file from the second echo command are only applied to the working copy, not the version in the staging area.

So, when git commit -m "Comment on Venus as an unsuitable base" is executed, the version of venus.txt committed to the repository is the one from the staging area and has only one line.

At this time, the working copy still has the second line (and git status will show that the file is modified). However, git checkout HEAD venus.txt replaces the working copy with the most recently committed version of venus.txt.

So, cat venus.txt will output

出力

Venus is beautiful and full of love.

git diffの理解のチェック

このコマンドをよく考えてみてください: git diff HEAD~9 mars.txt。 このコマンドを実行したらどうなるだろうと予測しますか? 実行すると何が起こっていますか? またそれはなぜでしょうか?

別のコマンド git diff [ID] mars.txt を試しましょう、ここでの [ID] は最新のコミットのユニークな ID で置き換えられます。 あなたは何が起こるだろうと思いますか?

ステージされた変更の除去

git checkout は、ステージされていない変更があったときに 以前のコミットを復元するために使用できます。しかしそれはステージされているがコミットされていない変更に対しても機能するでしょうか? mars.txt に変更を用意し、その変更を加え(git addを使い)、git checkout を使い変更を取り除くことができるかどうか確かめましょう。

After adding a change, git checkout can not be used directly. Let’s look at the output of git status:

出力

On branch main
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   mars.txt

Note that if you don’t have the same output you may either have forgotten to change the file, or you have added it and committed it.

Using the command git checkout -- mars.txt now does not give an error, but it does not restore the file either. Git helpfully tells us that we need to use git reset first to unstage the file:

BASH

$ git reset HEAD mars.txt

出力

Unstaged changes after reset:
M	mars.txt

Now, git status gives us:

BASH

$ git status

出力

On branch main
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:   mars.txt

no changes added to commit (use "git add" and/or "git commit -a")

This means we can now use git checkout to restore the file to the previous commit:

BASH

$ git checkout -- mars.txt
$ git status

出力

On branch main
nothing to commit, working tree clean

履歴を探索し、要約する

履歴の探索はgitの重要な要素であり、特にそのコミットが数ヶ月前のものである場合は、適切なコミットIDを見つけるのが難しいことがよくあります。

planets プロジェクトに50を超えるファイルがあると考えてください。 あなたは mars.txt 中の特定のテキストが変更されたコミットを見つけたいとします。 git log と入力すると、非常に長いリストが表示されました。 どうやって探す範囲を限定しますか?

git diff コマンドを使用すると、1つの特定のファイルを探索できることを思い出してください、 例えば、git diff mars.txt 。 ここでも同様のアイデアを適用できます。

BASH

$ git log mars.txt

Unfortunately some of these commit messages are very ambiguous, e.g., update files. How can you search through these files?

Both git diff and git log are very useful and they summarize a different part of the history for you. Is it possible to combine both? Let’s try the following:

BASH

$ git log --patch mars.txt

You should get a long list of output, and you should be able to see both commit messages and the difference between each commit.

Question: What does the following command do?

BASH

$ git log --patch HEAD~9 *.txt

まとめ

  • git diff は、コミット間の違いを表示します。
  • git checkout は、ファイルの古いバージョンを復元します。

Content from ファイルを無視する


最終更新日:2024-02-25 | ページの編集

概要

質問

  • Git で追跡したくないファイルを指定するにはどうすればよいですか?

目的

  • Git で追跡したくないファイルを指定しましょう
  • ファイルを無視する利点を理解しましょう

Git に追跡して欲しくないファイル、例えばエディタが作成したバックアップファイルやデータ解析中に作られた中間ファイルなどは、どう対処すればいいのでしょう? 例として、いくつかファイルを作ってみましょう:

BASH

$ mkdir results
$ touch a.csv b.csv c.csv results/a.out results/b.out

そして Git が何と言うか見てみましょう:

BASH

$ git status

出力

On branch main
Untracked files:
  (use "git add <file>..." to include in what will be committed)

	a.csv
	b.csv
	c.csv
	results/

nothing added to commit but untracked files present (use "git add" to track)

これらのファイルをバージョンコントロールで保存するのはディスク容量の無駄になります。 さらに、これら全てが表示されると、本当に必要な変更点に集中できなくなってしまうかもしれないので、 Git にこれらのファイルを無視してもらいましょう。

これをするには、.gitignore というファイルをルートディレクトリに作ります:

BASH

$ nano .gitignore
$ cat .gitignore

出力

*.csv
results/

入力したパターンは、 Git に .dat で終わるファイル名とresults ディレクトリ内にあるファイルを無視するように指示しています。 (Git がすでに追跡しているファイルは、引き続き追跡されます。)

このファイルを作った後git status の出力を見てみると、大分綺麗になっています:

BASH

$ git status

出力

On branch main
Untracked files:
  (use "git add <file>..." to include in what will be committed)

	.gitignore

nothing added to commit but untracked files present (use "git add" to track)

Git は新しく作られた .gitignore ファイルしか表示していません。 このファイルは追跡しなくても良いかと思うでしょうが、リポジトリを共有する際に、他の人達も私達が無視したものを同じように無視したいでしょう。 なので、.gitignore を追加してコミットしましょう:

BASH

$ git add .gitignore
$ git commit -m "Ignore data files and the results folder"
$ git status

出力

On branch main
nothing to commit, working tree clean

.gitignore を作った事によって、間違えて不要なファイルをリポジトリに追加する事を防ぐことができます:

BASH

$ git add a.csv

出力

The following paths are ignored by one of your .gitignore files:
a.csv
Use -f if you really want to add them.

この設定を強制的に無視してファイルを追加するには、git add -f を使います。 例えば、git add -f a.csv と入力します。 もちろん、無視されたファイルの状況はいつでも見ることができます:

BASH

$ git status --ignored

出力

On branch main
Ignored files:
 (use "git add -f <file>..." to include in what will be committed)

        a.csv
        b.csv
        c.csv
        results/

nothing to commit, working tree clean

埋もれた(ネストされた)ファイルを無視する

以下のようなディレクトリ構造があるとします:

BASH

results/data
results/plots

results/data ではなく、results/plots のみを無視するにはどうすればいいのでしょう?

results/plots 内のファイルのみを無視するのであれば、.gitignore/plots/ サブフォルダを無視するように.gitignore に以下の文を加えれば解決できます:

出力

results/plots/

この行によって、results/plotsの内容だけが無視され、results/dataの内容は無視されません。

様々なプログラミングの問題と同様に、この無視ルールが守られるようにする回答方法はいくつかありま。 「ネストされたファイルを無視する:バリエーション」の演習は、わずかに異なるディレクトリ構造を持っており、別の解決策を提示しています。「ネストされたファイルを無視する:バリエーション」の演習は、わずかに異なるディレクトリ構造を持っており、別の解決策を提示しています。 Further, the discussion page has more detail on ignore rules.

Including Specific Files

final.csv以外の、ルートディレクトリ内にある他の .data ファイルを全て無視したい場合はどうすればいいのでしょう? ヒント: ! (感嘆符)が何をするのか調べてみましょう。

以下二文を .gitignore に加えましょう:

出力

*.data           # 全ての data ファイルを無視する
!final.data      # final.data は対象から除外する

感嘆符は、無視してあったファイルを対象から外します。

このレッスンで.csvファイルをコミットしたことがあるので、この新しいルールでは無視されません。 Only future additions of .csv files added to the root directory will be ignored.

Ignoring Nested Files: Variation

Given a directory structure that looks similar to the earlier Nested Files exercise, but with a slightly different directory structure:

BASH

results/data
results/images
results/plots
results/analysis

How would you ignore all of the contents in the results folder, but not results/data?

Hint: think a bit about how you created an exception with the ! operator before.

If you want to ignore the contents of results/ but not those of results/data/, you can change your .gitignore to ignore the contents of results folder, but create an exception for the contents of the results/data subfolder. Your .gitignore would look like this:

出力

results/*               # ignore everything in results folder
!results/data/          # do not ignore results/data/ contents

ディレクトリ内の全てのデータファイルを無視する

空の.gitignoreファイルがあり、以下のようなディレクトリ構造があるとします:

BASH

results/data/position/gps/a.csv
results/data/position/gps/b.csv
results/data/position/gps/c.csv
results/data/position/gps/info.txt
results/plots

result/data/position/gps 内にある全ての .data ファイルを無視する一番短い.gitignoreルールは何でしょう? info.txt ファイルは無視しないでください。

results/data/position/gps/*.data を使えば results/data/position/gps 内にある全ての .data ファイルを無視できます。 results/data/position/gps/info.txt ファイルは無視されません。

Ignoring all data Files in the repository

Let us assume you have many .csv files in different subdirectories of your repository. For example, you might have:

BASH

results/a.csv
data/experiment_1/b.csv
data/experiment_2/c.csv
data/experiment_2/variation_1/d.csv

How do you ignore all the .csv files, without explicitly listing the names of the corresponding folders?

In the .gitignore file, write:

出力

**/*.csv

This will ignore all the .csv files, regardless of their position in the directory tree. You can still include some specific exception with the exclamation point operator.

ルールの順番

以下の内容の .gitignore ファイルがあるとします:

BASH

*.csv
!*.csv

結果的に何が無視されるのでしょうか?

感嘆符 ! は無視してあったファイルを対象から除外する効果があります。 !*.csv は、その前に入力されている .csv ファイルを対象から外すので、全ての .csv ファイルは引き続き追跡されることになります。

ログファイル

仮に log_01log_02log_03、というように、中間的にログファイルを作成するスクリプトを書いたとします。 これらのログファイルは取っておきたいのですが、git で追跡したくありません。

  1. log_01log_02、などのファイルを無視するためのルールを一つだけ .gitignore に入力してください。

  2. 入力したパターン正常に動作しているか確認するために log_01 などのファイルを作成してください。

  3. 最終的に log_01 ファイルがものすごく重要であることが分かりました。.gitignore を編集せずに、このファイルを追跡しているファイルに加えてください。

  4. 隣の人と、追跡したくないファイルは他にどのようなものがあるのか、そして.gitignore に何を入力すればこれらのファイルを無視できるのかを話し合ってください。

  1. log_* もしくは log* を .gitignore に加えます。

  2. git add -f log_01 を使って log_01 を追跡しましょう。

まとめ

  • .gitignore で無視するファイルを指定する

Content from GitHub におけるリモート


最終更新日:2024-03-28 | ページの編集

概要

質問

  • 自分の変更をウェブ上で他の人と共有するにはどうすればよいですか?

目的

  • リモートリポジトリとは何なのか、そしてなぜそれが役立つのかを説明します。
  • リモートリポジトリへのプッシュまたはリモートリポジトリからのプル。

バージョン管理が真価を発揮するのは、他の人々と共同作業を始めるときです。 これを行うために必要な機構のほとんどはすでに揃っています。 唯一欠けているのは、あるリポジトリから別のリポジトリに変更をコピーすることです。

Git のようなシステムを使用すると、任意の 2 つのリポジトリ間で作業結果を動かすことができます。 ただし、実際には、1 つのコピーを中央ハブとして使用し、それを誰かのラップトップではなくウェブ上に 保管するのが最も簡単です。 ほとんどのプログラマーは、GitHubBitbucket、あるいは GitLab のようなホスティングサービス に、これらのメインコピーを保持しています。この長所と短所については、後のエピソード で探ります。

まずは、現在のプロジェクトに加えた変更を世界と共有することから始めましょう。 この目的のために、ローカル リポジトリにリンクされる リモート リポジトリを作成します。

1. リモートリポジトリを作成する。


GitHub にログインし、右上隅のアイコンをクリックして planets という名前の新しいリポジトリを作成してみましょう:

Creating a Repository on GitHub (Step 1)

リポジトリに「planets」という名前を付けて、「Create Repository」をクリックします。

注: このリポジトリはローカルのリポジトリに接続されるため、空にしておく必要があります。 「Initialize this repository with a README」のチェックを外したままにし、「Add .gitignore」と「Add a license.」の両方のオプションを「None」のままにします。 リポジトリを空にしておく必要がある理由の完全な説明については、以下の「GitHub ライセンスと README ファイル」の演習を参照してください。

Creating a Repository on GitHub (Step 2)

リポジトリが作成されるとすぐに、GitHub には ある URL と、ローカルのリポジトリの構成方法に関する情報が記載されたページが表示されます。

Creating a Repository on GitHub (Step 3)

これにより、GitHub のサーバー上で次のことが効果的に行われます。

BASH

$ mkdir planets
$ cd planets
$ git init

もしあなたが以前の エピソード を覚えていれば、私達は mars.txt に以前の作業を追加してコミットしました。 ローカルリポジトリのダイアグラムは次のようになります:

The Local Repository with Git Staging Area

Now that we have two repositories, we need a diagram like this:

Freshly-Made GitHub Repository

Note that our local repository still contains our earlier work on mars.txt, but the remote repository on GitHub appears empty as it doesn’t contain any files yet.

2. Connect local to remote repository


Now we connect the two repositories. We do this by making the GitHub repository a remote for the local repository. The home page of the repository on GitHub includes the URL string we need to identify it:

Where to Find Repository URL on GitHub

Click on the ‘SSH’ link to change the protocol from HTTPS to SSH.

HTTPS vs. SSH

We use SSH here because, while it requires some additional configuration, it is a security protocol widely used by many applications. The steps below describe SSH at a minimum level for GitHub.

Changing the Repository URL on GitHub

Copy that URL from the browser, go into the local planets repository, and run this command:

BASH

$ git remote add origin git@github.com:vlad/planets.git

Make sure to use the URL for your repository rather than Vlad’s: the only difference should be your username instead of vlad.

origin is a local name used to refer to the remote repository. It could be called anything, but origin is a convention that is often used by default in git and GitHub, so it’s helpful to stick with this unless there’s a reason not to.

We can check that the command has worked by running git remote -v:

BASH

$ git remote -v

出力

origin   git@github.com:vlad/planets.git (fetch)
origin   git@github.com:vlad/planets.git (push)

We’ll discuss remotes in more detail in the next episode, while talking about how they might be used for collaboration.

3. SSH Background and Setup


Before Dracula can connect to a remote repository, he needs to set up a way for his computer to authenticate with GitHub so it knows it’s him trying to connect to his remote repository.

We are going to set up the method that is commonly used by many different services to authenticate access on the command line. This method is called Secure Shell Protocol (SSH). SSH is a cryptographic network protocol that allows secure communication between computers using an otherwise insecure network.

SSH uses what is called a key pair. This is two keys that work together to validate access. One key is publicly known and called the public key, and the other key called the private key is kept private. Very descriptive names.

You can think of the public key as a padlock, and only you have the key (the private key) to open it. You use the public key where you want a secure method of communication, such as your GitHub account. You give this padlock, or public key, to GitHub and say “lock the communications to my account with this so that only computers that have my private key can unlock communications and send git commands as my GitHub account.”

What we will do now is the minimum required to set up the SSH keys and add the public key to a GitHub account.

Advanced SSH

A supplemental episode in this lesson discusses SSH and key pairs in more depth and detail.

The first thing we are going to do is check if this has already been done on the computer you’re on. Because generally speaking, this setup only needs to happen once and then you can forget about it.

Keeping your keys secure

You shouldn’t really forget about your SSH keys, since they keep your account secure. It’s good practice to audit your secure shell keys every so often. Especially if you are using multiple computers to access your account.

We will run the list command to check what key pairs already exist on your computer.

BASH

ls -al ~/.ssh

Your output is going to look a little different depending on whether or not SSH has ever been set up on the computer you are using.

Dracula has not set up SSH on his computer, so his output is

出力

ls: cannot access '/c/Users/Vlad Dracula/.ssh': No such file or directory

If SSH has been set up on the computer you’re using, the public and private key pairs will be listed. The file names are either id_ed25519/id_ed25519.pub or id_rsa/id_rsa.pub depending on how the key pairs were set up.
Since they don’t exist on Dracula’s computer, he uses this command to create them.

3.1 Create an SSH key pair

To create an SSH key pair Vlad uses this command, where the -t option specifies which type of algorithm to use and -C attaches a comment to the key (here, Vlad’s email):

BASH

$ ssh-keygen -t ed25519 -C "vlad@tran.sylvan.ia"

If you are using a legacy system that doesn’t support the Ed25519 algorithm, use: $ ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

出力

Generating public/private ed25519 key pair.
Enter file in which to save the key (/c/Users/Vlad Dracula/.ssh/id_ed25519):

We want to use the default file, so just press Enter.

出力

Created directory '/c/Users/Vlad Dracula/.ssh'.
Enter passphrase (empty for no passphrase):

Now, it is prompting Dracula for a passphrase. Since he is using his lab’s laptop that other people sometimes have access to, he wants to create a passphrase. Be sure to use something memorable or save your passphrase somewhere, as there is no “reset my password” option.

出力

Enter same passphrase again:

After entering the same passphrase a second time, we receive the confirmation

出力

Your identification has been saved in /c/Users/Vlad Dracula/.ssh/id_ed25519
Your public key has been saved in /c/Users/Vlad Dracula/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:SMSPIStNyA00KPxuYu94KpZgRAYjgt9g4BA4kFy3g1o vlad@tran.sylvan.ia
The key's randomart image is:
+--[ED25519 256]--+
|^B== o.          |
|%*=.*.+          |
|+=.E =.+         |
| .=.+.o..        |
|....  . S        |
|.+ o             |
|+ =              |
|.o.o             |
|oo+.             |
+----[SHA256]-----+

The “identification” is actually the private key. You should never share it. The public key is appropriately named. The “key fingerprint” is a shorter version of a public key.

Now that we have generated the SSH keys, we will find the SSH files when we check.

BASH

ls -al ~/.ssh

出力

drwxr-xr-x 1 Vlad Dracula 197121   0 Jul 16 14:48 ./
drwxr-xr-x 1 Vlad Dracula 197121   0 Jul 16 14:48 ../
-rw-r--r-- 1 Vlad Dracula 197121 419 Jul 16 14:48 id_ed25519
-rw-r--r-- 1 Vlad Dracula 197121 106 Jul 16 14:48 id_ed25519.pub

3.2 Copy the public key to GitHub

Now we have a SSH key pair and we can run this command to check if GitHub can read our authentication.

BASH

ssh -T git@github.com

出力

The authenticity of host 'github.com (192.30.255.112)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? y
Please type 'yes', 'no' or the fingerprint: yes
Warning: Permanently added 'github.com' (RSA) to the list of known hosts.
git@github.com: Permission denied (publickey).

Right, we forgot that we need to give GitHub our public key!

First, we need to copy the public key. Be sure to include the .pub at the end, otherwise you’re looking at the private key.

BASH

cat ~/.ssh/id_ed25519.pub

出力

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDmRA3d51X0uu9wXek559gfn6UFNF69yZjChyBIU2qKI vlad@tran.sylvan.ia

Now, going to GitHub.com, click on your profile icon in the top right corner to get the drop-down menu. Click “Settings,” then on the settings page, click “SSH and GPG keys,” on the left side “Account settings” menu. Click the “New SSH key” button on the right side. Now, you can add the title (Dracula uses the title “Vlad’s Lab Laptop” so he can remember where the original key pair files are located), paste your SSH key into the field, and click the “Add SSH key” to complete the setup.

Now that we’ve set that up, let’s check our authentication again from the command line.

BASH

$ ssh -T git@github.com

出力

Hi Vlad! You've successfully authenticated, but GitHub does not provide shell access.

Good! This output confirms that the SSH key works as intended. We are now ready to push our work to the remote repository.

4. Push local changes to a remote


Now that authentication is setup, we can return to the remote. This command will push the changes from our local repository to the repository on GitHub:

BASH

$ git push origin main

Since Dracula set up a passphrase, it will prompt him for it. If you completed advanced settings for your authentication, it will not prompt for a passphrase.

出力

Enumerating objects: 16, done.
Counting objects: 100% (16/16), done.
Delta compression using up to 8 threads.
Compressing objects: 100% (11/11), done.
Writing objects: 100% (16/16), 1.45 KiB | 372.00 KiB/s, done.
Total 16 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), done.
To https://github.com/vlad/planets.git
 * [new branch]      main -> main

Proxy

If the network you are connected to uses a proxy, there is a chance that your last command failed with “Could not resolve hostname” as the error message. To solve this issue, you need to tell Git about the proxy:

BASH

$ git config --global http.proxy http://user:password@proxy.url
$ git config --global https.proxy https://user:password@proxy.url

When you connect to another network that doesn’t use a proxy, you will need to tell Git to disable the proxy using:

BASH

$ git config --global --unset http.proxy
$ git config --global --unset https.proxy

Password Managers

If your operating system has a password manager configured, git push will try to use it when it needs your username and password. For example, this is the default behavior for Git Bash on Windows. If you want to type your username and password at the terminal instead of using a password manager, type:

BASH

$ unset SSH_ASKPASS

in the terminal, before you run git push. Despite the name, Git uses , so you may want to unset SSH_ASKPASS whether you are using Git via SSH or https.

You may also want to add unset SSH_ASKPASS at the end of your ~/.bashrc to make Git default to using the terminal for usernames and passwords.

Our local and remote repositories are now in this state:

GitHub Repository After First Push

The ‘-u’ Flag

You may see a -u option used with git push in some documentation. This option is synonymous with the --set-upstream-to option for the git branch command, and is used to associate the current branch with a remote branch so that the git pull command can be used without any arguments. To do this, simply use git push -u origin main once the remote has been set up.

We can pull changes from the remote repository to the local one as well:

BASH

$ git pull origin main

出力

From https://github.com/vlad/planets
 * branch            main     -> FETCH_HEAD
Already up-to-date.

Pulling has no effect in this case because the two repositories are already synchronized. If someone else had pushed some changes to the repository on GitHub, though, this command would download them to our local repository.

GitHub GUI

Browse to your planets repository on GitHub. Underneath the Code button, find and click on the text that says “XX commits” (where “XX” is some number). Hover over, and click on, the three buttons to the right of each commit. What information can you gather/explore from these buttons? How would you get that same information in the shell?

The left-most button (with the picture of a clipboard) copies the full identifier of the commit to the clipboard. In the shell, git log will show you the full commit identifier for each commit.

When you click on the middle button, you’ll see all of the changes that were made in that particular commit. Green shaded lines indicate additions and red ones removals. In the shell we can do the same thing with git diff. In particular, git diff ID1..ID2 where ID1 and ID2 are commit identifiers (e.g. git diff a3bf1e5..041e637) will show the differences between those two commits.

The right-most button lets you view all of the files in the repository at the time of that commit. To do this in the shell, we’d need to checkout the repository at that particular time. We can do this with git checkout ID where ID is the identifier of the commit we want to look at. If we do this, we need to remember to put the repository back to the right state afterwards!

Uploading files directly in GitHub browser

Github also allows you to skip the command line and upload files directly to your repository without having to leave the browser. There are two options. First you can click the “Upload files” button in the toolbar at the top of the file tree. Or, you can drag and drop files from your desktop onto the file tree. You can read more about this on this GitHub page.

GitHub Timestamp

Create a remote repository on GitHub. Push the contents of your local repository to the remote. Make changes to your local repository and push these changes. Go to the repo you just created on GitHub and check the timestamps of the files. How does GitHub record times, and why?

GitHub displays timestamps in a human readable relative format (i.e. “22 hours ago” or “three weeks ago”). However, if you hover over the timestamp, you can see the exact time at which the last change to the file occurred.

Push vs. Commit

In this episode, we introduced the “git push” command. How is “git push” different from “git commit”?

When we push changes, we’re interacting with a remote repository to update it with the changes we’ve made locally (often this corresponds to sharing the changes we’ve made with others). Commit only updates your local repository.

GitHub License and README files

In this episode we learned about creating a remote repository on GitHub, but when you initialized your GitHub repo, you didn’t add a README.md or a license file. If you had, what do you think would have happened when you tried to link your local and remote repositories?

In this case, we’d see a merge conflict due to unrelated histories. When GitHub creates a README.md file, it performs a commit in the remote repository. When you try to pull the remote repository to your local repository, Git detects that they have histories that do not share a common origin and refuses to merge.

BASH

$ git pull origin main

出力

warning: no common commits
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From https://github.com/vlad/planets
 * branch            main     -> FETCH_HEAD
 * [new branch]      main     -> origin/main
fatal: refusing to merge unrelated histories

You can force git to merge the two repositories with the option --allow-unrelated-histories. Be careful when you use this option and carefully examine the contents of local and remote repositories before merging.

BASH

$ git pull --allow-unrelated-histories origin main

出力

From https://github.com/vlad/planets
 * branch            main     -> FETCH_HEAD
Merge made by the 'recursive' strategy.
README.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 README.md

まとめ

  • A local Git repository can be connected to one or more remote repositories.
  • Use the SSH protocol to connect to remote repositories.
  • git push copies changes from a local repository to a remote repository.
  • git pull copies changes from a remote repository to a local repository.

Content from Collaborating


最終更新日:2024-03-28 | ページの編集

概要

質問

  • How can I use version control to collaborate with other people?

目的

  • Clone a remote repository.
  • Collaborate by pushing to a common repository.
  • Describe the basic collaborative workflow.

For the next step, get into pairs. One person will be the “Owner” and the other will be the “Collaborator”. The goal is that the Collaborator add changes into the Owner’s repository. We will switch roles at the end, so both persons will play Owner and Collaborator.

Practicing By Yourself

If you’re working through this lesson on your own, you can carry on by opening a second terminal window. This window will represent your partner, working on another computer. You won’t need to give anyone access on GitHub, because both ‘partners’ are you.

The Owner needs to give the Collaborator access. In your repository page on GitHub, click the “Settings” button on the right, select “Collaborators”, click “Add people”, and then enter your partner’s username.

screenshot of repository page with Settings then Collaborators selected, showing how to add Collaborators in a GitHub repository

To accept access to the Owner’s repo, the Collaborator needs to go to https://github.com/notifications or check for email notification. Once there she can accept access to the Owner’s repo.

Next, the Collaborator needs to download a copy of the Owner’s repository to her machine. This is called “cloning a repo”.

The Collaborator doesn’t want to overwrite her own version of planets.git, so needs to clone the Owner’s repository to a different location than her own repository with the same name.

To clone the Owner’s repo into her Desktop folder, the Collaborator enters:

BASH

$ git clone git@github.com:vlad/planets.git ~/Desktop/vlad-planets

Replace ‘vlad’ with the Owner’s username.

If you choose to clone without the clone path (~/Desktop/vlad-planets) specified at the end, you will clone inside your own planets folder! Make sure to navigate to the Desktop folder first.

After Creating Clone of Repository

The Collaborator can now make a change in her clone of the Owner’s repository, exactly the same way as we’ve been doing before:

BASH

$ cd ~/Desktop/vlad-planets
$ nano pluto.txt
$ cat pluto.txt

出力

It is so a planet!

BASH

$ git add pluto.txt
$ git commit -m "Add notes about Pluto"

出力

 1 file changed, 1 insertion(+)
 create mode 100644 pluto.txt

Then push the change to the Owner’s repository on GitHub:

BASH

$ git push origin main

出力

Enumerating objects: 4, done.
Counting objects: 4, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 306 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/vlad/planets.git
   9272da5..29aba7c  main -> main

Note that we didn’t have to create a remote called origin: Git uses this name by default when we clone a repository. (This is why origin was a sensible choice earlier when we were setting up remotes by hand.)

Take a look at the Owner’s repository on GitHub again, and you should be able to see the new commit made by the Collaborator. You may need to refresh your browser to see the new commit.

Some more about remotes

In this episode and the previous one, our local repository has had a single “remote”, called origin. A remote is a copy of the repository that is hosted somewhere else, that we can push to and pull from, and there’s no reason that you have to work with only one. For example, on some large projects you might have your own copy in your own GitHub account (you’d probably call this origin) and also the main “upstream” project repository (let’s call this upstream for the sake of examples). You would pull from upstream from time to time to get the latest updates that other people have committed.

Remember that the name you give to a remote only exists locally. It’s an alias that you choose - whether origin, or upstream, or fred - and not something intrinstic to the remote repository.

The git remote family of commands is used to set up and alter the remotes associated with a repository. Here are some of the most useful ones:

  • git remote -v lists all the remotes that are configured (we already used this in the last episode)
  • git remote add [name] [url] is used to add a new remote
  • git remote remove [name] removes a remote. Note that it doesn’t affect the remote repository at all - it just removes the link to it from the local repo.
  • git remote set-url [name] [newurl] changes the URL that is associated with the remote. This is useful if it has moved, e.g. to a different GitHub account, or from GitHub to a different hosting service. Or, if we made a typo when adding it!
  • git remote rename [oldname] [newname] changes the local alias by which a remote is known - its name. For example, one could use this to change upstream to fred.

To download the Collaborator’s changes from GitHub, the Owner now enters:

BASH

$ git pull origin main

出力

remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From https://github.com/vlad/planets
 * branch            main     -> FETCH_HEAD
   9272da5..29aba7c  main     -> origin/main
Updating 9272da5..29aba7c
Fast-forward
 pluto.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 pluto.txt

Now the three repositories (Owner’s local, Collaborator’s local, and Owner’s on GitHub) are back in sync.

A Basic Collaborative Workflow

In practice, it is good to be sure that you have an updated version of the repository you are collaborating on, so you should git pull before making our changes. The basic collaborative workflow would be:

  • update your local repo with git pull origin main,
  • make your changes and stage them with git add,
  • commit your changes with git commit -m, and
  • upload the changes to GitHub with git push origin main

It is better to make many commits with smaller changes rather than of one commit with massive changes: small commits are easier to read and review.

Switch Roles and Repeat

Switch roles and repeat the whole process.

Review Changes

The Owner pushed commits to the repository without giving any information to the Collaborator. How can the Collaborator find out what has changed with command line? And on GitHub?

On the command line, the Collaborator can use git fetch origin main to get the remote changes into the local repository, but without merging them. Then by running git diff main origin/main the Collaborator will see the changes output in the terminal.

On GitHub, the Collaborator can go to the repository and click on “commits” to view the most recent commits pushed to the repository.

Comment Changes in GitHub

The Collaborator has some questions about one line change made by the Owner and has some suggestions to propose.

With GitHub, it is possible to comment on the diff of a commit. Over the line of code to comment, a blue comment icon appears to open a comment window.

The Collaborator posts her comments and suggestions using the GitHub interface.

Version History, Backup, and Version Control

Some backup software can keep a history of the versions of your files. They also allows you to recover specific versions. How is this functionality different from version control? What are some of the benefits of using version control, Git and GitHub?

まとめ

  • git clone copies a remote repository to create a local repository with a remote called origin automatically set up.

Content from Conflicts


最終更新日:2024-02-25 | ページの編集

概要

質問

  • What do I do when my changes conflict with someone else’s?

目的

  • Explain what conflicts are and when they can occur.
  • Resolve conflicts resulting from a merge.

As soon as people can work in parallel, they’ll likely step on each other’s toes. This will even happen with a single person: if we are working on a piece of software on both our laptop and a server in the lab, we could make different changes to each copy. Version control helps us manage these conflicts by giving us tools to resolve overlapping changes.

To see how we can resolve conflicts, we must first create one. The file mars.txt currently looks like this in both partners’ copies of our planets repository:

BASH

$ cat mars.txt

出力

Cold and dry, but everything is my favorite color
The two moons may be a problem for Wolfman
But the Mummy will appreciate the lack of humidity

Let’s add a line to the collaborator’s copy only:

BASH

$ nano mars.txt
$ cat mars.txt

出力

Cold and dry, but everything is my favorite color
The two moons may be a problem for Wolfman
But the Mummy will appreciate the lack of humidity
This line added to Wolfman's copy

and then push the change to GitHub:

BASH

$ git add mars.txt
$ git commit -m "Add a line in our home copy"

出力

[main 5ae9631] Add a line in our home copy
 1 file changed, 1 insertion(+)

BASH

$ git push origin main

出力

Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 331 bytes | 331.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
To https://github.com/vlad/planets.git
   29aba7c..dabb4c8  main -> main

Now let’s have the owner make a different change to their copy without updating from GitHub:

BASH

$ nano mars.txt
$ cat mars.txt

出力

Cold and dry, but everything is my favorite color
The two moons may be a problem for Wolfman
But the Mummy will appreciate the lack of humidity
We added a different line in the other copy

We can commit the change locally:

BASH

$ git add mars.txt
$ git commit -m "Add a line in my copy"

出力

[main 07ebc69] Add a line in my copy
 1 file changed, 1 insertion(+)

but Git won’t let us push it to GitHub:

BASH

$ git push origin main

出力

To https://github.com/vlad/planets.git
 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'https://github.com/vlad/planets.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
The Conflicting Changes

Git rejects the push because it detects that the remote repository has new updates that have not been incorporated into the local branch. What we have to do is pull the changes from GitHub, merge them into the copy we’re currently working in, and then push that. Let’s start by pulling:

BASH

$ git pull origin main

出力

remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (1/1), done.
remote: Total 3 (delta 2), reused 3 (delta 2), pack-reused 0
Unpacking objects: 100% (3/3), done.
From https://github.com/vlad/planets
 * branch            main     -> FETCH_HEAD
    29aba7c..dabb4c8  main     -> origin/main
Auto-merging mars.txt
CONFLICT (content): Merge conflict in mars.txt
Automatic merge failed; fix conflicts and then commit the result.

The git pull command updates the local repository to include those changes already included in the remote repository. After the changes from remote branch have been fetched, Git detects that changes made to the local copy overlap with those made to the remote repository, and therefore refuses to merge the two versions to stop us from trampling on our previous work. The conflict is marked in in the affected file:

BASH

$ cat mars.txt

出力

Cold and dry, but everything is my favorite color
The two moons may be a problem for Wolfman
But the Mummy will appreciate the lack of humidity
<<<<<<< HEAD
We added a different line in the other copy
=======
This line added to Wolfman's copy
>>>>>>> dabb4c8c450e8475aee9b14b4383acc99f42af1d

Our change is preceded by <<<<<<< HEAD. Git has then inserted ======= as a separator between the conflicting changes and marked the end of the content downloaded from GitHub with >>>>>>>. (The string of letters and digits after that marker identifies the commit we’ve just downloaded.)

It is now up to us to edit this file to remove these markers and reconcile the changes. We can do anything we want: keep the change made in the local repository, keep the change made in the remote repository, write something new to replace both, or get rid of the change entirely. Let’s replace both so that the file looks like this:

BASH

$ cat mars.txt

出力

Cold and dry, but everything is my favorite color
The two moons may be a problem for Wolfman
But the Mummy will appreciate the lack of humidity
We removed the conflict on this line

To finish merging, we add mars.txt to the changes being made by the merge and then commit:

BASH

$ git add mars.txt
$ git status

出力

On branch main
All conflicts fixed but you are still merging.
  (use "git commit" to conclude merge)

Changes to be committed:

	modified:   mars.txt

BASH

$ git commit -m "Merge changes from GitHub"

出力

[main 2abf2b1] Merge changes from GitHub

Now we can push our changes to GitHub:

BASH

$ git push origin main

出力

Enumerating objects: 10, done.
Counting objects: 100% (10/10), done.
Delta compression using up to 8 threads
Compressing objects: 100% (6/6), done.
Writing objects: 100% (6/6), 645 bytes | 645.00 KiB/s, done.
Total 6 (delta 4), reused 0 (delta 0)
remote: Resolving deltas: 100% (4/4), completed with 2 local objects.
To https://github.com/vlad/planets.git
   dabb4c8..2abf2b1  main -> main

Git keeps track of what we’ve merged with what, so we don’t have to fix things by hand again when the collaborator who made the first change pulls again:

BASH

$ git pull origin main

出力

remote: Enumerating objects: 10, done.
remote: Counting objects: 100% (10/10), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 6 (delta 4), reused 6 (delta 4), pack-reused 0
Unpacking objects: 100% (6/6), done.
From https://github.com/vlad/planets
 * branch            main     -> FETCH_HEAD
    dabb4c8..2abf2b1  main     -> origin/main
Updating dabb4c8..2abf2b1
Fast-forward
 mars.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

We get the merged file:

BASH

$ cat mars.txt

出力

Cold and dry, but everything is my favorite color
The two moons may be a problem for Wolfman
But the Mummy will appreciate the lack of humidity
We removed the conflict on this line

We don’t need to merge again because Git knows someone has already done that.

Git’s ability to resolve conflicts is very useful, but conflict resolution costs time and effort, and can introduce errors if conflicts are not resolved correctly. If you find yourself resolving a lot of conflicts in a project, consider these technical approaches to reducing them:

  • Pull from upstream more frequently, especially before starting new work
  • Use topic branches to segregate work, merging to main when complete
  • Make smaller more atomic commits
  • Push your work when it is done and encourage your team to do the same to reduce work in progress and, by extension, the chance of having conflicts
  • Where logically appropriate, break large files into smaller ones so that it is less likely that two authors will alter the same file simultaneously

Conflicts can also be minimized with project management strategies:

  • Clarify who is responsible for what areas with your collaborators
  • Discuss what order tasks should be carried out in with your collaborators so that tasks expected to change the same lines won’t be worked on simultaneously
  • If the conflicts are stylistic churn (e.g. tabs vs. spaces), establish a project convention that is governing and use code style tools (e.g. htmltidy, perltidy, rubocop, etc.) to enforce, if necessary

Solving Conflicts that You Create

Clone the repository created by your instructor. Add a new file to it, and modify an existing file (your instructor will tell you which one). When asked by your instructor, pull her changes from the repository to create a conflict, then resolve it.

Conflicts on Non-textual files

What does Git do when there is a conflict in an image or some other non-textual file that is stored in version control?

Let’s try it. Suppose Dracula takes a picture of Martian surface and calls it mars.jpg.

If you do not have an image file of Mars available, you can create a dummy binary file like this:

BASH

$ head -c 1024 /dev/urandom > mars.jpg
$ ls -lh mars.jpg

出力

-rw-r--r-- 1 vlad 57095 1.0K Mar  8 20:24 mars.jpg

ls shows us that this created a 1-kilobyte file. It is full of random bytes read from the special file, /dev/urandom.

Now, suppose Dracula adds mars.jpg to his repository:

BASH

$ git add mars.jpg
$ git commit -m "Add picture of Martian surface"

出力

[main 8e4115c] Add picture of Martian surface
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 mars.jpg

Suppose that Wolfman has added a similar picture in the meantime. His is a picture of the Martian sky, but it is also called mars.jpg. When Dracula tries to push, he gets a familiar message:

BASH

$ git push origin main

出力

To https://github.com/vlad/planets.git
 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'https://github.com/vlad/planets.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

We’ve learned that we must pull first and resolve any conflicts:

BASH

$ git pull origin main

When there is a conflict on an image or other binary file, git prints a message like this:

出力

$ git pull origin main
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://github.com/vlad/planets.git
 * branch            main     -> FETCH_HEAD
   6a67967..439dc8c  main     -> origin/main
warning: Cannot merge binary files: mars.jpg (HEAD vs. 439dc8c08869c342438f6dc4a2b615b05b93c76e)
Auto-merging mars.jpg
CONFLICT (add/add): Merge conflict in mars.jpg
Automatic merge failed; fix conflicts and then commit the result.

The conflict message here is mostly the same as it was for mars.txt, but there is one key additional line:

出力

warning: Cannot merge binary files: mars.jpg (HEAD vs. 439dc8c08869c342438f6dc4a2b615b05b93c76e)

Git cannot automatically insert conflict markers into an image as it does for text files. So, instead of editing the image file, we must check out the version we want to keep. Then we can add and commit this version.

On the key line above, Git has conveniently given us commit identifiers for the two versions of mars.jpg. Our version is HEAD, and Wolfman’s version is 439dc8c0.... If we want to use our version, we can use git checkout:

BASH

$ git checkout HEAD mars.jpg
$ git add mars.jpg
$ git commit -m "Use image of surface instead of sky"

出力

[main 21032c3] Use image of surface instead of sky

If instead we want to use Wolfman’s version, we can use git checkout with Wolfman’s commit identifier, 439dc8c0:

BASH

$ git checkout 439dc8c0 mars.jpg
$ git add mars.jpg
$ git commit -m "Use image of sky instead of surface"

出力

[main da21b34] Use image of sky instead of surface

We can also keep both images. The catch is that we cannot keep them under the same name. But, we can check out each version in succession and rename it, then add the renamed versions. First, check out each image and rename it:

BASH

$ git checkout HEAD mars.jpg
$ git mv mars.jpg mars-surface.jpg
$ git checkout 439dc8c0 mars.jpg
$ mv mars.jpg mars-sky.jpg

Then, remove the old mars.jpg and add the two new files:

BASH

$ git rm mars.jpg
$ git add mars-surface.jpg
$ git add mars-sky.jpg
$ git commit -m "Use two images: surface and sky"

出力

[main 94ae08c] Use two images: surface and sky
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 mars-sky.jpg
 rename mars.jpg => mars-surface.jpg (100%)

Now both images of Mars are checked into the repository, and mars.jpg no longer exists.

A Typical Work Session

You sit down at your computer to work on a shared project that is tracked in a remote Git repository. During your work session, you take the following actions, but not in this order:

  • Make changes by appending the number 100 to a text file numbers.txt
  • Update remote repository to match the local repository
  • Celebrate your success with some fancy beverage(s)
  • Update local repository to match the remote repository
  • Stage changes to be committed
  • Commit changes to the local repository

In what order should you perform these actions to minimize the chances of conflicts? Put the commands above in order in the action column of the table below. When you have the order right, see if you can write the corresponding commands in the command column. A few steps are populated to get you started.

order action . . . . . . . . . . command . . . . . . . . . .
1
2 echo 100 >> numbers.txt
3
4
5
6 Celebrate! AFK
order action . . . . . . command . . . . . . . . . . . . . . . . . . .
1 Update local git pull origin main
2 Make changes echo 100 >> numbers.txt
3 Stage changes git add numbers.txt
4 Commit changes git commit -m "Add 100 to numbers.txt"
5 Update remote git push origin main
6 Celebrate! AFK

まとめ

  • Conflicts occur when two or more people change the same lines of the same file.
  • The version control system does not allow people to overwrite each other’s changes blindly, but highlights conflicts so that they can be resolved.

Content from オープン サイエンス


最終更新日:2024-02-25 | ページの編集

概要

質問

  • バージョン管理は、私の研究をよりオープンにするのにどのように役立ちますか?

目的

  • バージョン管理システムを計算実験用の電子実験ノートとしてどのように活用できるか説明しましょう。

“open” の反対は “closed” ではありません。 “open” の反対は “broken” です。

-– John Wilbanks

科学では情報を自由に共有することが理想的かもしれませんが、現実はもっと複雑なことがよくあります。 最近のよくあるやり方は次のようになります。

  • 科学者は何らかのデータを収集し、それを自分の部門によって時折バックアップされるマシンに保存します。
  • 次に、科学者はそのデータを分析するために、いくつかの小さなプログラム(これもその科学者のマシンにあります)を作成または変更します。
  • 結果が出たら、それを書き留めて論文を提出します。 科学者は自分のデータを含めるかもしれません – ますます多くのジャーナルがこれを必要としています – しかし科学者はおそらく自分のコードを含めていません。
  • 時間が経過します。
  • ジャーナルは、科学者の分野の他の少数の人々によって匿名で書かれたレビューを科学者に送信します。 科学者はレビューした人を納得させるために自分の論文を改訂し、その間に科学者は以前に書いたスクリプトを修正し、論文を再提出するかもしれません。
  • さらに時間が経過します。
  • ついに論文が出版されます。 科学者のデータのオンラインコピーへのリンクが含まれている可能性がありますが、論文自体はペイウォールの背後にあるでしょう:個人的または組織的なアクセス権を持つ人だけがそれを読むことができるでしょう。

しかし、ますます多くの科学者にとって、そのプロセスは次のようになります:

  • figshareZenodoなどのオープンアクセスリポジトリに保存され、独自のデジタルオブジェクト識別子 (DOI) が与えられます。 または、データはすでに公開されており、Dryad に保存されています。
  • 科学者は、自分の研究を保持するためにGitHubに新しいリポジトリを作成します。
  • 科学者は分析を行うときに、スクリプト (場合によってはいくつかの出力ファイルも) への変更をそのリポジトリにプッシュします。 科学者はまた、自分の論文用にそのリポジトリを使用します;そしてそのリポジトリは、同僚とのコラボレーションのハブになります。
  • 論文の状態に満足したら、arXivまたはその他のプレプリントサーバーに版を投稿し、仲間からのフィードバックを求めます。
  • そのフィードバックに基づいて、科学者は最終的に論文をジャーナルに投稿する前に、いくつかの改訂を投稿する可能性があります。
  • 公開された論文には、科学者のプレプリントとコードそしてデータリポジトリへのリンクが含まれているため、他の科学者が論文の研究を自分の研究の出発点として使用するのがはるかに簡単になります。

このオープンモデルは発見を加速します:研究結果がオープンになっていればなっているほど、 広く引用され、再利用されます。 ただし、このように作業したい人は、正確に “オープン” が何を意味し、それをどのように行うかについて、いくつかの決定を下す必要があります。 この本では、オープンサイエンスのさまざまな側面について詳しく知ることができます。

これは、バージョン管理を教える (多くの) 理由の1つです。 コツコツと使うと、計算作業のための共有可能な電子ラボノートとして機能することによって、 バージョン管理は “どのように” の質問に答えてくれます:

  • 誰がいつ何をしたかなど、作業の概念的な段階が文書化されています。 すべてのステップには、(ほとんどの場合)固有の識別子 (コミットID) がスタンプされています。
  • 理論的根拠、アイデア、およびその他の知的作業の文書化を、それらから生じる変化に直接結び付けることができます。
  • 独自の回復可能な方法で計算結果を取得するために、研究で使用したものを参照できるようになります。
  • Gitなどのバージョン管理システムを使用すると、リポジトリの履歴全体を簡単にアーカイブして永続化できます。

コードを引用可能にすること

バージョン管理リポジトリでホストされているもの(データ、コード、論文など)はすべて、 引用可能なオブジェクトに変換できます。これを行う方法は、 これを行う方法は、レッスン 12: 引用で学習します。

私の仕事はどれくらい再現可能ですか?

ラボメイトの1人に、あなたの論文やウェブで見つけることができるものだけを使用して、あなたが最近得た結果を再現するように依頼してみましょう。 ラボメイトの結果の1つに対して同じことを行ってみてから、あなたの研究室由来の結果にそれを行ってみてください。

適切なデータリポジトリを見つける方法は?

数分間インターネットサーフィンして、次のデータリポジトリをチェックしてみましょう:Figshare, ZenodoDryad。 研究分野によっては、その分野でよく知られたコミュニティで認められたリポジトリが見つかるかもしれません。 Natureが推奨するこれらのデータリポジトリも便利かもしれません。 現在のプロジェクト用にどのデータリポジトリにアプローチしたいかを隣人と議論し、その理由を説明してみましょう。

How to Track Large Data or Image Files using Git?

Large data or image files such as .md5 or .psd file types can be tracked within a github repository using the Git Large File Storage open source extension tool. This tool automatically uploads large file contents to a remote server and replaces the file with a text pointer within the github repository.

Try downloading and installing the Git Large File Storage extension tool, then add tracking of a large file to your github repository. Ask a colleague to clone your repository and describe what they see when they access that large file.

まとめ

  • オープンな科学的研究は、クローズドよりも有用であり、引用数が多い。

Content from Licensing


最終更新日:2024-02-25 | ページの編集

概要

質問

  • What licensing information should I include with my work?

目的

  • Explain why adding licensing information to a repository is important.
  • Choose a proper license.
  • Explain differences in licensing and social expectations.

When a repository with source code, a manuscript or other creative works becomes public, it should include a file LICENSE or LICENSE.txt in the base directory of the repository that clearly states under which license the content is being made available. This is because creative works are automatically eligible for intellectual property (and thus copyright) protection. Reusing creative works without a license is dangerous, because the copyright holders could sue you for copyright infringement.

A license solves this problem by granting rights to others (the licensees) that they would otherwise not have. What rights are being granted under which conditions differs, often only slightly, from one license to another. In practice, a few licenses are by far the most popular, and choosealicense.com will help you find a common license that suits your needs. Important considerations include:

  • Whether you want to address patent rights.
  • Whether you require people distributing derivative works to also distribute their source code.
  • Whether the content you are licensing is source code.
  • Whether you want to license the code at all.

Choosing a license that is in common use makes life easier for contributors and users, because they are more likely to already be familiar with the license and don’t have to wade through a bunch of jargon to decide if they’re ok with it. The Open Source Initiative and Free Software Foundation both maintain lists of licenses which are good choices.

This article provides an excellent overview of licensing and licensing options from the perspective of scientists who also write code.

At the end of the day what matters is that there is a clear statement as to what the license is. Also, the license is best chosen from the get-go, even if for a repository that is not public. Pushing off the decision only makes it more complicated later, because each time a new collaborator starts contributing, they, too, hold copyright and will thus need to be asked for approval once a license is chosen.

Can I Use Open License?

Find out whether you are allowed to apply an open license to your software. Can you do this unilaterally, or do you need permission from someone in your institution? If so, who?

What licenses have I already accepted?

Many of the software tools we use on a daily basis (including in this workshop) are released as open-source software. Pick a project on GitHub from the list below, or one of your own choosing. Find its license (usually in a file called LICENSE or COPYING) and talk about how it restricts your use of the software. Is it one of the licenses discussed in this session? How is it different?

  • Git, the source-code management tool
  • CPython, the standard implementation of the Python language
  • Jupyter, the project behind the web-based Python notebooks we’ll be using
  • EtherPad, a real-time collaborative editor

まとめ

  • The LICENSE, LICENSE.md, or LICENSE.txt file is often used in a repository to indicate how the contents of the repo may be used by others.
  • People who incorporate General Public License (GPL’d) software into their own software must make their software also open under the GPL license; most other open licenses do not require this.
  • The Creative Commons family of licenses allow people to mix and match requirements and restrictions on attribution, creation of derivative works, further sharing, and commercialization.
  • People who are not lawyers should not try to write licenses from scratch.

Content from Citation


最終更新日:2024-02-25 | ページの編集

概要

質問

  • How can I make my work easier to cite?

目的

  • Make your work easy to cite

You may want to include a file called CITATION or CITATION.txt that describes how to reference your project; the one for Software Carpentry states:

To reference Software Carpentry in publications, please cite both of the following:

Greg Wilson: "Software Carpentry: Getting Scientists to Write Better
Code by Making Them More Productive".  Computing in Science &
Engineering, Nov-Dec 2006.

Greg Wilson: "Software Carpentry: Lessons Learned". arXiv:1307.5448,
July 2013.

@article{wilson-software-carpentry-2006,
    author =  {Greg Wilson},
    title =   {Software Carpentry: Getting Scientists to Write Better Code by Making Them More Productive},
    journal = {Computing in Science \& Engineering},
    month =   {November--December},
    year =    {2006},
}

@online{wilson-software-carpentry-2013,
  author      = {Greg Wilson},
  title       = {Software Carpentry: Lessons Learned},
  version     = {1},
  date        = {2013-07-20},
  eprinttype  = {arxiv},
  eprint      = {1307.5448}
}

More detailed advice, and other ways to make your code citable can be found at the Software Sustainability Institute blog and in:

Smith AM, Katz DS, Niemeyer KE, FORCE11 Software Citation Working Group. (2016) Software citation
principles. [PeerJ Computer Science 2:e86](https://peerj.com/articles/cs-86/)
https://doi.org/10.7717/peerj-cs.8

There is also an @software{... BibTeX entry type in case no “umbrella” citation like a paper or book exists for the project you want to make citable.

まとめ

  • Add a CITATION file to a repository to explain how you want your work cited.

Content from Hosting


最終更新日:2024-02-25 | ページの編集

概要

質問

  • バージョン管理リポジトリはどこでホストすればよいでしょうか?

目的

  • 科学研究のホスティングのためのさまざまなオプションについて説明します。

自分たちの仕事をオープンにしたいグループにとって次に大きな問題は、コードとデータをどこにホストするかです。 1 つのオプションは、研究室、学部、または大学がサーバーを提供し、アカウントやバックアップなどを管理することです。 これの主な利点は、誰が何を所有しているかを明確にすることです。 それは、題材が機密性の高いもの (すなわち、ヒトを対象とする実験に関するもの、または特許出願に使用される可能性のあるもの) である場合に特に重要です。 主な欠点は、サービスの提供コストとその存続期間です。データ収集に 10 年を費やした科学者は、10 年後もデータが利用できることを確認したいと考えますが、それは学術インフラに資金提供されるほとんど助成金の存続期間をはるかに超えています。

もう 1 つのオプションは、ドメインを購入し、それをホストするためにインターネット サービス プロバイダー (ISP) に料金を支払うことです。 これにより、個人またはグループによる制御が強化され、ある機関から別の機関に移動するときに発生する可能性のある問題を回避できます。 ただし、上記のオプションまたは下記のオプションよりもセットアップに多くの時間と労力が必要です。

3 番目のオプションは、 GitHubGitLab、または BitBucket のようなパブリック ホスティング サービスを使用することです。 これらの各サービスは、コードリポジトリを作成、閲覧、編集できる Web インターフェイスを提供します。 これらのサービスは、イシュートラッキング、Wiki ページ、メール通知、コードレビューなどのコミュニケーションやプロジェクト管理ツールも提供します。 These services benefit from economies of scale and network effects: it’s easier to run one large service well than to run many smaller services to the same standard. It’s also easier for people to collaborate. Using a popular service can help connect your project with communities already using the same service.

As an example, Software Carpentry is on GitHub where you can find the source for this page. Anyone with a GitHub account can suggest changes to this text.

GitHub repositories can also be assigned DOIs, by connecting its releases to Zenodo. For example, 10.5281/zenodo.7908089 is the DOI that has been “minted” for this introduction to Git.

Using large, well-established services can also help you quickly take advantage of powerful tools. One such tool, continuous integration (CI), can automatically run software builds and tests whenever code is committed or pull requests are submitted. Direct integration of CI with an online hosting service means this information is present in any pull request, and helps maintain code integrity and quality standards. While CI is still available in self-hosted situations, there is much less setup and maintenance involved with using an online service. Furthermore, such tools are often provided free of charge to open source projects, and are also available for private repositories for a fee.

Institutional Barriers

Sharing is the ideal for science, but many institutions place restrictions on sharing, for example to protect potentially patentable intellectual property. If you encounter such restrictions, it can be productive to inquire about the underlying motivations and either to request an exception for a specific project or domain, or to push more broadly for institutional reform to support more open science.

Can My Work Be Public?

Find out whether you are allowed to host your work openly in a public repository. Can you do this unilaterally, or do you need permission from someone in your institution? If so, who?

Where Can I Share My Work?

Does your institution have a repository or repositories that you can use to share your papers, data and software? How do institutional repositories differ from services like arXiV, figshare, GitHub or GitLab?

まとめ

  • Projects can be hosted on university servers, on personal domains, or on a public hosting service.
  • Rules regarding intellectual property and storage of sensitive information apply no matter where code and data are hosted.

Content from Supplemental: Using Git from RStudio


最終更新日:2024-02-25 | ページの編集

概要

質問

  • How can I use Git with RStudio?

目的

  • Understand how to use Git from RStudio.

Version control can be very useful when developing data analysis scripts. For that reason, the popular development environment RStudio for the R programming language has built-in integration with Git. While some advanced Git features still require the command-line, RStudio has a nice interface for many common Git operations.

RStudio allows us to create a project associated with a given directory to keep track of various related files. To be able to track the development of the project over time, to be able to revert to previous versions, and to collaborate with others, we version control the Rstudio project with Git. To get started using Git in RStudio, we create a new project:

RStudio screenshot showing the file menu dropdown with "New Project..." selected

This opens a dialog asking us how we want to create the project. We have some options here. Let’s say that we want to use RStudio with the planets repository that we already made. Since that repository lives in a directory on our computer, we choose the option “Existing Directory”:

RStudio screenshot showing New Project dialog window with "Create project from existing directory" selected

Do You See a “Version Control” Option?

Although we’re not going to use it here, there should be a “version control” option on this menu. That is what you would click on if you wanted to create a project on your computer by cloning a repository from GitHub. If that option is not present, it probably means that RStudio doesn’t know where your Git executable is, and you won’t be able to progress further in this lesson until you tell RStudio where it is.

Find your Git Executable

First let’s make sure that Git is installed on your computer. Open your shell on Mac or Linux, or on Windows open the command prompt and then type:

  • which git (macOS, Linux)
  • where git (Windows)

If there is no version of Git on your computer, please follow the Git installation instructions in the setup of this lesson to install Git now. Next open your shell or command prompt and type which git (macOS, Linux), or where git (Windows). Copy the path to the git executable.

On one Windows computer which had GitHub Desktop installed on it, the path was: C:/Users/UserName/AppData/Local/GitHubDesktop/app-1.1.1/resources/app/git/cmd/git.exe

NOTE: The path on your computer will be somewhat different.

Tell RStudio where to find GitHub

In RStudio, go to the Tools menu > Global Options > Git/SVN and then browse to the Git executable you found in the command prompt or shell. Now restart RStudio. Note: Even if you have Git installed, you may need to accept the Xcode license if you are using macOS.

Next, RStudio will ask which existing directory we want to use. Click “Browse…” and navigate to the correct directory, then click “Create Project”:

Ta-da! We have created a new project in RStudio within the existing planets repository. Notice the vertical “Git” menu in the menu bar. RStudio has recognized that the current directory is a Git repository, and gives us a number of tools to use Git:

RStudio window after new project is created with large arrow pointing to vertical Git menu bar.

To edit the existing files in the repository, we can click on them in the “Files” panel on the lower right. Now let’s add some additional information about Pluto:

Once we have saved our edited files, we can use RStudio to commit the changes by clicking on “Commit…” in the Git menu:

RStudio screenshot showing the Git menu dropdown with "Commit..." selected

This will open a dialogue where we can select which files to commit (by checking the appropriate boxes in the “Staged” column), and enter a commit message (in the upper right panel). The icons in the “Status” column indicate the current status of each file. Clicking on a file shows information about changes in the lower panel (using output of git diff). Once everything is the way we want it, we click “Commit”:

The changes can be pushed by selecting “Push Branch” from the Git menu. There are also options to pull from the remote repository, and to view the commit history:

RStudio screenshot showing the git menu dropdown with "History" selected

Are the Push/Pull Commands Grayed Out?

Grayed out Push/Pull commands generally mean that RStudio doesn’t know the location of your remote repository (e.g. on GitHub). To fix this, open a terminal to the repository and enter the command: git push -u origin main. Then restart RStudio.

If we click on “History”, we can see a graphical version of what git log would tell us:

RStudio creates a number of files that it uses to keep track of a project. We often don’t want to track these, in which case we add them to our .gitignore file:

RStudio screenshot showing .gitignore open in the editor pane with the files .Rproj.user, .Rhistory, .RData, and *.Rproj added to the end

Tip: versioning disposable output

Generally you do not want to version control disposable output (or read-only data). You should modify the .gitignore file to tell Git to ignore these files and directories.

チャレンジ

  1. Create a new directory within your project called graphs.
  2. Modify the .gitignore so that the graphs directory is not version controlled.

This can be done in Rstudio:

R

dir.create("./graphs")

Then open up the .gitignore file from the right-hand panel of Rstudio and add graphs/ to the list of files to ignore.

There are many more features in the RStudio Git menu, but these should be enough to get you started!

まとめ

  • Using RStudio’s Git integration allows you to version control a project over time.