Linux/Unix環境でのGit入門
- 更新履歴
- はじめに
- バージョン管理システム
- 集中と分散
- 分散型バージョン管理ソフトウェアGit
- ブランチ管理
- Gitの良く使われるコマンドとリポジトリ、インデックス、作業ツリーの関係
- Gitコマンドの練習
- 初期設定(エディタの設定)
- Gitがインストール済みかどうかの確認
- Gitのインストール(自分で準備したLinuxの場合)
- 作業ディレクトリの作成
- リポジトリの作成 (init, config)
- ファイルの追加 (add)
- 変更履歴のリポジトリへの保存(commit)
- 変更履歴の閲覧(log)
- 任意の時点との差分の表示(diff)
- ファイル名の変更、移動および削除(mv, rm)
- オンラインマニュアル(help)
- 1リポジトリ上の基本操作まとめ
- ブランチの確認、作成、名前変更、削除 (branch)
- ブランチ間の移動 (checkout)
- 他ブランチの変更履歴の現ブランチへの反映 (merge)
- 競合・衝突(conflict)とその解消
- ブランチの基本操作まとめ
- 作業ツリーなしリポジトリの作成(init --bare)
- リモートリポジトリの設定(remote)
- リモートリポジトリにローカルリポジトリの内容を反映させる(push)
- リモートリポジトリのコピー(clone)
- リモートリポジトリの内容をローカルリポジトリへ反映させる(pull)
- リポジトリ間の基本操作まとめ
- ファイルの各行がどのコミットで変更されたのかを調べる(blame)
- ブランチをグラフ形式で見る(log --graph)
- 過去のコミットからブランチを作成する/ファイルを作成する(checkoutの発展的使い方)
- Gitコマンドまとめ
- 参考リンク
- Gitフロントエンドの使い方
- 戻る
更新履歴_
- 2020年5月4日: Ubuntu 18.04上での作業用に更新
- 2020年5月8日: MacOS上の作業について追加
はじめに_
このページにはUbuntu 18.04を前提として構築されている部分があります。適宜、自分の環境に読み替えてください。
Mac OSの方はこちらのページを参考にしてください。
このページの画像は以下のスライドと同じです。
バージョン管理システム_
バージョン管理システム(Version Control System, VCS)とは、コンピュータ上で作成、編集されるファイルの変更履歴を管理するためのソフトウェアのこと。
VCSは以下のような状況を解決するために使用される。
- 間違ってファイルを消してしまった
- 変更を保存した後に、変更前の方が良いことに気付いた
- 複数人でファイルを編集しているとき、どの変更を誰が行ったのかわからない
代表的なVCSには以下のようなものがある。
- 集中管理:RCS、CVS、Subversion
- 分散管理:Git、Mercurial
集中と分散_
VCSでは、変更履歴(リビジョン、Revision。ファイルの編集前と編集後の差分、編集日時、編集者、および、編集に対する編集者のコメント)をリポジトリと呼ばれるデータベースに格納して保管している。

現在のVCSはリポジトリの管理方法から集中型と分散型の2つの種類に分類できる。
集中型VCSでは、1つのリポジトリを1箇所で管理する。作業ディレクトリのファイル/ディレクトリの変更履歴をリポジトリに保存するのが「コミット (commit)」と呼ばれる操作である。リポジトリから(変更履歴を反映させた)ファイルやディレクトリを取り出すのが「チェックアウト (checkout)」と呼ばれる操作である。

一方、分散型VCSは、複数のリポジトリを複数の箇所で分散的に管理する。分散VCSではリポジトリ間で格納している変更履歴の同期をとることができる。ローカルリポジトリの変更履歴をリモートリポジトリ(別の場所にあるリポジトリ)へ送るのが「プッシュ (push)」という操作であり、その逆が「プル (pull)」という操作である。リモートリポジトリをローカルにコピーするのが「クローン (clone)」という操作である。

分散型バージョン管理ソフトウェアGit_
Gitは分散VCSの一種である。Gitは、Linux kernelのソースコード管理のために提案・開発されているバージョン管理システムであり、最近、もっともよく利用されている分散VCSである。
リポジトリ間の通信方式として以下のものを用意している。
- ファイルシステム(同一計算機上の場合)
- SSH (Secure Shell)
- Git専用プロトコル(認証機能なし)
- HTTP/HTTPS(WebDAV)(pushするためにはWebDAVが必要)
ネットワークに接続できないときでも、リポジトリに変更履歴を保存できるという利点の他に、集中VCSでは大変な作業であったブランチ管理を簡単に行えるという利点がある。
ブランチ管理_
変更履歴の分岐のことを「ブランチ (branch)」という。Gitにおいてはブランチはブランチを管理する操作名でもある。

ブランチを1つにまとめる操作を「マージ(merge)」という。ブランチ間で変更履歴に矛盾がない場合は、マージは問題なく成功するが、矛盾がある場合(同じ部分に異なる変更がほどこされている場合)は、「衝突 (conflict)」が発生したとみなされ、編集者による衝突の解決が必要となる。

Gitの良く使われるコマンドとリポジトリ、インデックス、作業ツリーの関係_

Gitコマンドの練習_
初期設定(エディタの設定)_
git内で用いるエディタの設定を行う.Ubuntu上のお好きなエディタを用いること。
- 標準では nano, vimがインストール済みである。
- WSL上のUbuntu18.04でのEmacs
- エディタGEDITのインストールと日本語入力環境の整備
以下ではエディタとしてemacsを使うこととする。Ubuntu 18.04 LTSは標準ではシェルにbashを用いている。そこで、~/.bash_profileを編集する。
% echo "export EDITOR='emacs -nw'" >> ~/.bash_profile % source ~/.bash_profile % env | grep EDITOR EDITOR=emacs -nw
Gitがインストール済みかどうかの確認_
% which git /usr/bin/git (gitが存在するディレクトリが表示されたならばOK)
バージョンも確認してみる。Ubuntu 18.04 LTSのGitのバージョンは結構古い(2020年5月4日現在の最新バージョン 2.26.2 ⇒ Git)
% git --version git version 2.17.1
Gitのインストール(自分で準備したLinuxの場合)_
- RedHat、CentOS系の場合
% sudo yum install git
- Debian, Ubuntu系の場合
% sudo apt install git
インストールに成功したかどうかをwhichコマンドで確かめる。
% which git
作業ディレクトリの作成_
以下の作業はGitがインストール済み(サーチパスも通してある)のLinuxでの作業と仮定する。
まず、作業ディレクトリを作ります。
% cd % mkdir -p GitSandbox % ls % cd GitSandbox
リポジトリの作成 (init, config)_
gitには「作業ツリー+リポジトリ」と「リポジトリのみ」の作成方法がある。まず、頻繁に利用する「作業ツリー+リポジトリ」を作成する。
% mkdir firstrepo % ls % cd firstrepo % git init
リポジトリは.gitというディレクトリ内に生成される。削除しないように注意する。
% ls -a % ls -a .git
つづいて、このリポジトリにおけるユーザ名とメールアドレスを設定する。Gitでは編集履歴に「誰が」編集したのかを記録するため、ユーザ名とメールアドレスの設定が不可欠である。自分の名前と自分のメールアドレス(今回は大学発行のメールアドレスにしておく)に置き換えて入力すること。
% git config --global user.name "Yuichi Goto" % git config --global user.email gotoh@aise.ics.saitama-u.ac.jp % git config -l
なお、このリポジトリだけで設定したい場合は global オプションを外すとよい。
% git config user.name "Yuichi Goto" % git config user.email gotoh@aise.ics.saitama-u.ac.jp
ファイルの追加 (add)_
変更履歴をリポジトリに保管するために、Indexに保管対象のファイルを明示的に指定する必要がある。これは add コマンドを使う。以下の例では、新たに作成した Readme.md をGitでの管理対象にし、かつ、Indexへ登録している。
% touch Readme.md % git status (現在の変更対象、Indexへの追加状況を表示するコマンド) ブランチ master No commits yet 追跡されていないファイル: (use "git add <file>..." to include in what will be committed) Readme.md nothing added to commit but untracked files present (use "git add" to track) % git add Readme.md % git status ブランチ master No commits yet コミット予定の変更点: (use "git rm --cached <file>..." to unstage) new file: Readme.md
既に管理対象になっているファイルであっても、変更をほどこしたならば add コマンドで Indexに追加する必要がある(後述)
変更履歴のリポジトリへの保存(commit)_
Index に列挙されているファイルの変更履歴をリポジトリへ保存する。この操作を commit という。Gitでは commit を行う場合に必ずコメントを登録しなければならない。今回はコメントとして「First commit.」と入力する。
% git commit (コメント追加のためのエディタが起動する。emacsの場合、保存はC-x C-s) [master (root-commit) febc49e] First Commit. 0 files changed create mode 100644 Readme.md
参考:commitにオプションをつけることで、addコマンドを省いたり、コメントをエディタを開かずにつけることができる。
% git commit (コメント追加のためのエディタが起動する) % git commit -m "コメント" (一言コメントであれば-mオプションをつけると便利) % git commit -a (既に管理対象になっており、かつ、編集済のファイルをコミットする) % git commit -a -m "コメント" (-m と -a は同時に使うこともできる)
たとえば、Readme.mdを編集してみる。まず、emacsを起動する。
% emacs &
Readme.mdを以下のように編集する(emacs上で C-x C-f を押し、Readme.mdを開く)
## Introduction Hello, World! ## Conclusion Bye, bye!
すると、ファイルに編集済みであるが、Indexに追加されていない状態になっているのがわかる。
% git status ブランチ master 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: Readme.md no changes added to commit (use "git add" and/or "git commit -a")
先ほどの例に従うと以下のようにコマンドを実行し、変更履歴をリポジトリに格納すべきである(今回はこちらのコマンドは使わない)。
% git add Readme.md % git commit
上をまとめて実行すると以下のようになる。実行してみること。
% git commit -a -m "Second commit." [master d8dd1fc] Second commit. 1 file changed, 7 insertions(+)
変更履歴の閲覧(log)_
変更履歴を閲覧する場合は log コマンドを使う。「commit」の横に表示されているのがハッシュキー。リビジョンを区別するためのIDとして使われている。「Author」が編集者、「Date」が編集日時、そして、その下には commit 実行時のコメントが表示される。
% git log commit d8dd1fc15a5594bbeee12ef8a076fa0a7c8b9802 Author: Yuichi Goto <gotoh@aise.ics.saitama-u.ac.jp> Date: Tue Jun 2 13:17:41 2015 +0900 Second commit. commit febc49eac79a7c7525122e8166241060a89aa01d Author: Yuichi Goto <gotoh@aise.ics.saitama-u.ac.jp> Date: Tue Jun 2 13:12:31 2015 +0900 First Commit.
ログが多い場合は more コマンドと同様にページごとに表示される。
- ページ送り(1画面送り):スペースキー
- 1行送り:Enterキー
- 終了:qキー
任意の時点との差分の表示(diff)_
Readme.md を以下のように変更する。
## Introduction Hello, World! ## Section 1 An apple is a fruit. ## Conclusion Bye, bye!
そして、Indexに登録する。
% git add Readme.md
さらにReadme.md を以下のように変更する。
## Introduction Hello, World! ## Section 1 An apple is a fruit. ## Section 2 A dog is not a fruit. ## Conclustion Bye, bye!
これで、Readme.md について、3つの異なる内容が以下のように存在している。
- 現在のReadme.mdファイル(Section 1と2がある)
- Indexに登録されている変更(Section 1がある)
- リポジトリに保存されている最新のコミット(HEADという)(IntroductionとConclusionだけ)
現在の当該ファイルと過去の状態の差分を調べるためには diff コマンドを利用する。オプションなしの場合は、Indexに列挙されている状態と現在の状態の差分を表示する。
% git diff Readme.md diff --git a/Readme.md b/Readme.md index fe3df5c..ab37b41 100644 --- a/Readme.md +++ b/Readme.md @@ -6,6 +6,10 @@ Hello, World! An apple is a fruit. +## Section 2 + +A dog is not a fruit. + ## Conclusion Bye, bye!
cachedオプションをつけるとIndexとHEAD(リポジトリに登録された最新の変更履歴)との差分を表示する。
% git diff --cached Readme.md diff --git a/Readme.md b/Readme.md index 4c4b7d0..fe3df5c 100644 --- a/Readme.md +++ b/Readme.md @@ -2,6 +2,10 @@ Hello, World! +## Section 1 + +An apple is a fruit. + ## Conclusion Bye, bye!
オプションなしで、HEADを指定すると現在のファイルとHEADの差分を表示する。
% git diff HEAD Readme.md diff --git a/Readme.md b/Readme.md index 4c4b7d0..ab37b41 100644 --- a/Readme.md +++ b/Readme.md @@ -2,6 +2,14 @@ Hello, World! +## Section 1 + +An apple is a fruit. + +## Section 2 + +A dog is not a fruit. + ## Conclusion Bye, bye!
任意のリビジョンと比較する場合はコミットIDを指定する。最初のコミット「febc49eac79a7c7525122e8166241060a89aa01d」時点でのReadme.txtと現在のファイルの差分を表示する。
% git log commit d8dd1fc15a5594bbeee12ef8a076fa0a7c8b9802 Author: Yuichi Goto <gotoh@aise.ics.saitama-u.ac.jp> Date: Tue Jun 2 13:17:41 2015 +0900 Second commit. commit febc49eac79a7c7525122e8166241060a89aa01d Author: Yuichi Goto <gotoh@aise.ics.saitama-u.ac.jp> Date: Tue Jun 2 13:12:31 2015 +0900 First Commit. % git diff febc49eac79a7c7525122e8166241060a89aa01d Readme.md diff --git a/Readme.md b/Readme.md index e69de29..ab37b41 100644 --- a/Readme.md +++ b/Readme.md @@ -0,0 +1,15 @@ +## Introduction + +Hello, World! + +## Section 1 + +An apple is a fruit. + +## Section 2 + +A dog is not a fruit. + +## Conclusion + +Bye, bye!
一旦、commit する。
% git commit -a -m "Third commit"
ファイル名の変更、移動および削除(mv, rm)_
たとえば、新たに tmp_dir/newfile を追加するとする。
% mkdir tmp_dir % touch tmp_dir/newfile % git add tmp_dir/newfile % git commit -m "Add new file." % git log (終了はqキーを押す)
一度、リポジトリに登録したあとにこのディレクトリ名やファイル名を変更したい、また、ファイルの場所を移動させたいときには mv コマンドを使う。
% ls % git mv tmp_dir renamed_dir % ls % git status ブランチ master コミット予定の変更点: (use "git reset HEAD <file>..." to unstage) renamed: tmp_dir/newfile -> rename_dir/newfile % git mv renamed_dir/newfile ./newfile % ls % git status ブランチ master コミット予定の変更点: (use "git reset HEAD <file>..." to unstage) renamed: tmp_dir/newfile -> newfile % git commit -a -m "Renamed and moved a directory and a file."
なお、Gitでは空のディレクトリは管理対象から外される。
ファイルやディレクトリを削除するときには rm コマンドを使う。
% git rm newfile % ls % git status ブランチ master コミット予定の変更点: (use "git reset HEAD <file>..." to unstage) deleted: newfile % git commit -a -m "Removed a file."
オンラインマニュアル(help)_
Linuxコマンドのmanコマンドと同じように、gitの各命令に関するオンラインマニュアルを表示するコマンドhelpがある。
% git help
基本的にgitの命令は「git hogehoge」という形式になっている。このhogehogeについてオンラインマニュアルを表示したい場合には「git help hogehoge」と入力する。オンラインマニュアルの操作はmoreコマンドと同じ
- ページ送り(1画面送り):スペースキー
- 1行送り:Enterキー
- 終了:qキー
1リポジトリ上の基本操作まとめ_
ここまでの復習も兼ねて、オンラインマニュアルを眺めてみる。
まず、Gitで管理するディレクトリの作成コマンド
% git help init
各種設定コマンド
% git help config
管理対象のファイル追加
% git help add
変更履歴の保存
% git help commit
変更履歴のログ
% git help log
変更履歴間の差分表示
% git help diff
管理対象のファイルの名前変更、移動
% git help mv
管理対象のファイルの削除
% git help rm
1リポジトリ上の基本的な操作は以上となる。
ブランチの確認、作成、名前変更、削除 (branch)_

1人利用でのバックアップ方法としてGitを用いる場合にはブランチを気にする必要がないが、公開するソフトウェア開発や複数人での開発の際にはブランチを用いた方が便利である。
そこでブランチを作成する。status コマンドのコメントで「ブランチ master (On branch master)」という表示があったが、デフォルトのブランチは「master」ブランチである。個人でソフトウェアを開発し、かつ、Gitを使って管理する場合には GitHub flowが便利だと思う。
GitHub flowは master(稼働し、公開できるブランチ), dev(開発用ブランチ), その他トピックブランチ(機能追加やバグ修正ごとに作成するブランチ)の3種類のブランチを運用するブランチ管理モデルである。
ブランチの一覧を表示する場合は branch コマンドを使う。アスタリスクがついているブランチが現在のブランチである。
% git branch * master
新たに dev ブランチを作成する。
% git branch dev % git branch dev * master
トピックブランチ「tmp_b」を作成する。
% git branch tmp_b % git branch dev * master tmp_b
ブランチ名を変えたい場合はmオプションを使う。
% git branch -m tmp_b tmp_c % git branch dev * master tmp_c
ブランチを削除する場合はdオプションを使う
% git branch -d tmp_c Deleted branch tmp_c (was 7bb4c22). % git branch dev * master
ブランチ間の移動 (checkout)_
まず、カレントディレクトリが~/GitSandbox/firstrepoであることを確認する(ユーザ名によって絶対パスは異なるので注意。)
% pwd /home/gotoh/GitSandbox/firstrepo % ls -1 Readme.md rename_dir
まず、masterブランチで新たにファイルを付け加える。マージ(merge)の綴りが間違っているが、これは後で修正するので今はこのままとする。
% touch unmarged_file % git add unmarged_file % git commit -m "Add a file." % ls % git log
dev ブランチに移動する。移動は checkout コマンドを使う。
% git checkout dev Switched to branch 'dev' % git branch % ls % git log # unmarged_fileを追加したコミットがない。
この dev ブランチは unmarged_file を追加する前のリビジョンから分岐しているため、unmarged_file はこのブランチには含まれない。
このようにGit はブランチごとに作業ツリーをリポジトリから構築している。これにより、あるブランチでの変更を他のブランチにまったく影響させずに作業することができる。
他ブランチの変更履歴の現ブランチへの反映 (merge)_

他ブランチの変更履歴を現ブランチへ反映させる際には merge コマンドを使う。
% git branch % git merge master Updating 7bb4c22..caa8706 Fast-forward 0 files changed create mode 100644 unmarged_file
unmarged_fileが存在すること、また、同ファイルを追加したコミットがログに含まれていることを確認する。
% ls % git log
unmarged_file の merge の綴りがまちがっているので修正してコミットする。
% git mv unmarged_file unmerged_file % git commit -m "Modified spell miss." % ls
master ブランチへ戻る。当然、unmarged_fileはunmerged_fileに変更されていない(devブランチの変更は他のブランチに影響を与えない)。
% git checkout master % git branch % ls
dev ブランチの変更履歴をmaster ブランチへ反映させる。
% git merge dev % ls % git log
ここまでをまとめると以下のとおり。 あるブランチAの変更結果は他のブランチBに影響を与えない。Aの変更結果をBに反映させたい場合はマージを行う必要がある。手順は以下のとおり。
- まず、ブランチBに移動する。
% git checkout B
- 次にAをBにマージする。
% git merge A
競合・衝突(conflict)とその解消_
ブランチ間でgitが解決できない変更の競合・衝突が起きたときにどうなるかを確認してみる。
unmerged_file の中身を以下のように変更する。
## May be conflict. Hello.
コミットする。
% git commit -a -m "Edit unmerged_file on master."
dev ブランチへ移動する。masterブランチの変更結果はdevブランチに影響を与えないので、unmerged_file の中身は空のままである。
% git checkout dev % git branch % ls -l unmerged_file % more unmerged_file
unmerged_file の中身を以下のように変更する。なお、この際にはエディタでunmerged_fileを開きなおした上で作業すること。
## May be conflict. Good night.
コミットする。
% git commit -a -m "Edit unmerged_file on dev."
master ブランチの変更履歴を devブランチに反映させる。すると衝突が起こっていることが報告される。
% git merge master Auto-merging unmerged_file CONFLICT (content): Merge conflict in unmerged_file Automatic merge failed; fix conflicts and then commit the result.
unmerged_file は以下のようになっている。これはファイルの2行目が現在のブランチ(dev)の最新のコミット(HEAD)とmasterブランチのHEADとの間で食い違っていることを表している。
% more unmerged_file ## May be conflict <<<<<<< HEAD Good night. ======= Hello. >>>>>>> master
このように変更間に矛盾が発生し、Gitでは機械的に解決できないとき衝突が報告される。この場合は、人間が衝突を解消してあげないといけない。
衝突解決用ツールがインストールされている場合は mergetool コマンドで解決用ツールが立ち上がるがインストールされていない場合は以下のようなメッセージが表示される。
% git mergetool This message is displayed because 'merge.tool' is not configured. See 'git mergetool --tool-help' or 'git help config' for more details. 'git mergetool' will now attempt to use one of the following tools: opendiff kdiff3 tkdiff xxdiff meld tortoisemerge gvimdiff diffuse diffmerge ecmerge p4merge araxis bc codecompare emerge vimdiff Merging: unmerged_file Normal merge conflict for 'unmerged_file': {local}: modified file {remote}: modified file Hit return to start merge resolution tool (bc): (Enterキーを押す) The merge tool bc is not available as 'bcompare'
今回はエディタで衝突を解消する。エディタでunmerged_file を開きなおし、以下のように修正する。
## Solved the conflict. Good night. Hello.
コミットする。Gitが勝手にコメントをつけてくれる。
% git commit -a % git log
以上が衝突の発生、および、衝突の解消方法である。
次の作業のため master ブランチに戻り、mergeする。
% git checkout master % more unmerged_file % git merge dev % more unmerged_file
ブランチの基本操作まとめ_
ここまでの復習も兼ねて、オンラインマニュアルを眺めてみる。
ブランチ作成、名前変更、削除など
% git help branch
ブランチ間の移動、あるいは、作業ツリーの展開
% git help checkout
他のブランチの変更履歴の自ブランチへの反映
% git help merge
以上がブランチに関する基本操作である。
作業ツリーなしリポジトリの作成(init --bare)_

リポジトリ間の操作を練習するために二つ目のリポジトリを作業ツリーなしで作成する。
% cd ~/GitSandbox % mkdir secondrepo % cd secondrepo % git init --bare % ls -a # 作業ツリー+リポジトリの場合の.gitの中身が直接生成される
以後、この secondrepo をリモートリポジトリ(作業ツリーのあるリポジトリとデータのやりとりをする別の場所にあるリポジトリのこと)としてリポジトリ間の同期の練習を行なう。
リモートリポジトリの設定(remote)_
ここまで、 firstrepo ではリモートリポジトリを設定していなかった。リモートリポジトリの設定は remote コマンドを用いて行なう。まず、現在の設定を確認する。今のところリモートリポジトリは設定されていないので git remote -v コマンド何も表示されない。
% cd ../firstrepo % git remote -v
先ほど作成した secondrepo をリモートリポジトリとして設定する。リモートリポジトリは複数個設定することができる。標準で使うリポジトリは origin という名前をつけて管理することになっている。secondrepo は同一コンピュータ上に存在するのでファイルアクセスでリポジトリにアクセスする。
% pwd /home/gotoh/GitSandbox/firstrepo ## 「file://」にsecondrepoの絶対パス(pwdの出力結果で分かる)を入力すること % git remote add origin file:///home/gotoh/GitSandbox/secondrepo # git remote addの書式 % git remote add リポジトリ名 リモートリポジトリのURL(file://, ssh://, git://, https://, http://)
正しくリモートリポジトリが設定できているかを確認する。
% git remote -v origin file:///home/gotoh/GitSandbox/secondrepo (fetch) origin file:///home/gotoh/GitSandbox/secondrepo (push)
もし、リモートリポジトリのURL(今回の場合はリポジトリのある場所の絶対パス表記)が間違っているならば、以下のコマンドで修正する。
% git remote set-url リポジトリ名 リモートリポジトリのURL
リモートリポジトリのリポジトリ名を間違えた場合は、以下のコマンドでリポジトリ名を修正する。
% git remote rename 現在のリモートリポジトリ名 新しいリポートリポジトリ名
リモートリポジトリにローカルリポジトリの内容を反映させる(push)_
リモートリポジトリとローカルリポジトリ(現在作業しているリポジトリ)の間で変更履歴の同期をとることができる。ローカルリポジトリの変更履歴をリモートリポジトリに反映させるときはpushコマンドを用いる。
以下のように実行する。
% git push origin master % git push origin dev ## pushの書式 % git push リモートリポジトリ名 ブランチ名
これで、firstrepoのmasterブランチとdevブランチがsecondrepo に反映された。
リモートリポジトリのコピー(clone)_
すでに存在するリモートリポジトリの内容をコピーするときに clone コマンドを使う。cloneコマンドで3つめのリポジトリを作成する。cloneコマンドは標準では、コピー元のディレクトリ名と同じ名前のディレクトリ名でコピーしたリポジトリを作成してしまう(つまり、この例題だと GitSandbox 以下でcloneコマンドを実行すると失敗してしまう)。この例題ではthirdrepoというディレクトリ名でリポジトリのコピーをしている。
% cd .. % pwd /home/gotoh/GitSandbox % git clone file:///home/gotoh/GitSandbox/secondrepo fatal: destination path 'secondrepo' already exists and is not an empty directory. (標準ではリモートディレクトリの名前のディレクトリが生成される。 今回はsecondrepoがすでに存在するため上記のエラーがでている) % git clone file:///home/gotoh/GitSandbox/secondrepo thirdrepo % ls % cd thirdrepo
clone コマンドでコピーしてきたリポジトリでは、(基本的には)リモートリポジトリはコピー元のリポジトリになっている。
% git remote -v origin file:///home/gotoh/GitSandbox/secondrepo (fetch) origin file:///home/gotoh/GitSandbox/secondrepo (push)
cloneコマンドでリポジトリをコピーしてきた場合、ブランチは標準でmaster だけコピーされる。
% git branch * master
リモートリポジトリに存在するブランチも見たい場合は、branch コマンドに -a オプションをつける。
% git branch -a * master remotes/origin/HEAD -> origin/master remotes/origin/dev remotes/origin/master
リモートリポジトリに存在するブランチに対して checkout するとローカルにリモートのブランチがコピーされる。
% git checkout dev Branch dev set up to track remote branch dev from origin. Switched to a new branch 'dev' % git branch
Readme.mdにSection 3を付け加える。
## Introduction Hello, world! ## Section 1 An apple is a fruit. ## Section 2 A dog is not a fruit. ## Section 3 Everything is a fruit. ## Conclusion Bye, bye!
commitして、リモートリポジトリへpushする。
% git commit -a -m "Edit a file in third repository." % git push Counting objects: 3, done. Delta compression using up to 8 threads. Compressing objects: 100% (3/3), done. Writing objects: 100% (3/3), 360 bytes | 360.00 KiB/s, done. Total 3 (delta 1), reused 0 (delta 0) To file:///home/gotoh/GitSandbox/secondrepo e116920..51e5312 dev -> dev
リモートリポジトリの内容をローカルリポジトリへ反映させる(pull)_
ここまでで、secondrepoの内容は firstrepo よりもリビジョンが進んでいる。そこで、secondrepo の内容を firstrepo へ反映させる。リモートリポジトリの内容の反映は pull コマンドを用いる。
% cd ~/GitSandbox/firstrepo % git branch dev * master % more Readme.md (Section 3がない) % git pull origin master From file:///home/gotoh/GitSandbox/secondrepo * branch master -> FETCH_HEAD Already up-to-date. # pull コマンドの書式 % git pull リモートリポジトリ名 リモートリポジトリのブランチ名
現在、secondrepoとfirstrepoの内容は devブランチにおいてのみ違うため、masterブランチをpullしても何も変更はおこらない。
devブランチの変更をローカルリポジトリへ反映させる。
% git checkout dev % git pull origin dev remote: Counting objects: 3, done. remote: Compressing objects: 100% (3/3), done. remote: Total 3 (delta 1), reused 0 (delta 0) Unpacking objects: 100% (3/3), done. From file:///home/gotoh/GitSandbox/secondrepo * branch dev -> FETCH_HEAD e116920..51e5312 dev -> origin/dev Updating e116920..51e5312 Fast-forward Readme.md | 4 ++++ 1 file changed, 4 insertions(+) % more Readme.md % git log
これで、2つ目のリポジトリを経由して、1つ目と3つ目のリポジトリの同期を行なうことができた。
たとえば、ノートパソコンと自宅のデスクトップパソコンの間で同期をとりたい場合は以下のようにリポジトリを作って運用する。
- ノートパソコン上に作業ディレクトリ+リポジトリ
- ネットワーク上にリモートリポジトリ(多くの場合はGitHubやGitLab, backlogなどのGitフロントエンドを用いる)
- デスクトップパソコン上に作業ディレクトリ+リポジトリ
リポジトリ間の基本操作まとめ_
ここまでの復習も兼ねて、オンラインマニュアルを眺めてみる。
ローカルリポジトリと連携するリモートリポジトリの設定。
% git help remote
ローカルリポジトリの変更履歴をリモートリポジトリに反映させる。
% git help push
リモートリポジトリをローカルリポジトリとして保存する。
% git help clone
リモートリポジトリの変更履歴をローカルリポジトリに反映させる。
% git help pull
ファイルの各行がどのコミットで変更されたのかを調べる(blame)_
どの行がどのコミット(リビジョン)で変更されたのかを調べる場合は blame コマンドを使う。
% git blame Readme.md a0236847 (Yuichi Goto 2020-05-04 02:09:27 +0900 1) ## Introduction a0236847 (Yuichi Goto 2020-05-04 02:09:27 +0900 2) a0236847 (Yuichi Goto 2020-05-04 02:09:27 +0900 3) Hello, World! a0236847 (Yuichi Goto 2020-05-04 02:09:27 +0900 4) 61f60057 (Yuichi Goto 2020-05-04 02:17:44 +0900 5) ## Section 1 61f60057 (Yuichi Goto 2020-05-04 02:17:44 +0900 6) 61f60057 (Yuichi Goto 2020-05-04 02:17:44 +0900 7) An apple is a fruit. 61f60057 (Yuichi Goto 2020-05-04 02:17:44 +0900 8) 61f60057 (Yuichi Goto 2020-05-04 02:17:44 +0900 9) ## Section 2 61f60057 (Yuichi Goto 2020-05-04 02:17:44 +0900 10) 61f60057 (Yuichi Goto 2020-05-04 02:17:44 +0900 11) A dog is not a fruit. 61f60057 (Yuichi Goto 2020-05-04 02:17:44 +0900 12) 51e5312a (Yuichi Goto 2020-05-04 15:30:40 +0900 13) ## Section 3 51e5312a (Yuichi Goto 2020-05-04 15:30:40 +0900 14) 51e5312a (Yuichi Goto 2020-05-04 15:30:40 +0900 15) Everything is a fruit. 51e5312a (Yuichi Goto 2020-05-04 15:30:40 +0900 16) a0236847 (Yuichi Goto 2020-05-04 02:09:27 +0900 17) ## Conclusion a0236847 (Yuichi Goto 2020-05-04 02:09:27 +0900 18) a0236847 (Yuichi Goto 2020-05-04 02:09:27 +0900 19) Bye, bye!
ブランチをグラフ形式で見る(log --graph)_
どこで分岐してどこで合流したのかなど見ることができる。
% git log --graph --pretty=oneline * 51e5312a4997a960cc822be52a90170422691577 (HEAD -> dev, origin/dev) Edit a file in third repository. * e116920a894ff26b4ea1328e56c16073acdd711b (origin/master, master) Merge branch 'master' into dev |\ | * a6a16a86a997d69941f00ed1c28203b600d6e941 Edit unmerged_file on master. * | c8a40a2d35d5de19c5706264d12de40bd7583e39 Edit unmerged_file on dev. |/ * 9909c8d8ac094dca986ee8885a9d3473e1cae768 Modified spell miss. * aebc2ca892759391069089a67592b170a4b62235 Add a file. * 95fc2f9eccdadbbb3f91296cf3a181408acc4162 Removed a file. * 71606375bdf3311583444f1adb72e54d52aaadfe Renamed and moved a directory and a file. * ecab7a4204e3982963fb98fe978bb6c0514a4e19 Add new file. * 61f6005706995d83937bf306b91a2842a93252ff Third commit * a023684783cf46aeb35e896c58d5c3354505a5a3 Second commit. * 1b1121e369013a0ae7efdd24e7bc851677489da7 First commit.
過去のコミットからブランチを作成する/ファイルを作成する(checkoutの発展的使い方)_
作業を進めていく中で、一旦、ある時点まで戻って作業したくなることは良くある(たとえば、不要だと思って削除した部分が、やはり必要だったなど)。そのようなときには、過去のコミットからブランチを作成することで対応できる。
たとえば、途中で削除したnewfileを復活させる。まず、「git log」コマンドを使って、newfileを削除する直前のコミットを探す。
% git log --pretty=oneline ~中略~ 95fc2f9eccdadbbb3f91296cf3a181408acc4162 Removed a file. 71606375bdf3311583444f1adb72e54d52aaadfe Renamed and moved a directory and a file. ecab7a4204e3982963fb98fe978bb6c0514a4e19 Add new file. ~後略~
コミットのハッシュ値が「71606375bdf3311583444f1adb72e54d52aaadfe」の次のコミットでnewfileを削除していたのが分かる。このハッシュ値を使えば特定のファイルだけ過去のコミット時に戻すことや、過去のコミットを別ブランチとして呼び出すことが可能である。
- 「git checkout ハッシュ値 ファイル名」:特定のファイルだけを復帰させる
- 「git checkout ハッシュ値 -b 新ブランチ名」:過去のコミットの状態を別ブランチとして呼び出す
newfileを削除前のコミットから復帰させる。
% git checkout 71606375bdf3311583444f1adb72e54d52aaadfe newfile % ls (newfileが復帰していることを確認する) % git status ブランチ dev コミット予定の変更点: (use "git reset HEAD <file>..." to unstage) new file: newfile 追跡されていないファイル: (注:以下のファイルは衝突時のbcコマンドで生成された) (use "git add <file>..." to include in what will be committed) unmerged_file_BACKUP_13441 unmerged_file_BASE_13441 unmerged_file_LOCAL_13441 unmerged_file_REMOTE_13441
newfileが必要な場合はこのままコミットする。今回はコミットしてみる。
% git commit -a -m "Return newfile from previous commit." % git log --graph --pretty=oneline
別ブランチとして呼び出してみる。
% git log --pretty=oneline 2cbb4420f448e3e5d34baf10d74c6845fe196025 (HEAD -> dev) Return newfile from previous commit. 51e5312a4997a960cc822be52a90170422691577 (origin/dev) Edit a file in third repository. e116920a894ff26b4ea1328e56c16073acdd711b (origin/master, master) Merge branch 'master' into dev c8a40a2d35d5de19c5706264d12de40bd7583e39 Edit unmerged_file on dev. a6a16a86a997d69941f00ed1c28203b600d6e941 Edit unmerged_file on master. 9909c8d8ac094dca986ee8885a9d3473e1cae768 Modified spell miss. aebc2ca892759391069089a67592b170a4b62235 Add a file. 95fc2f9eccdadbbb3f91296cf3a181408acc4162 Removed a file. 71606375bdf3311583444f1adb72e54d52aaadfe Renamed and moved a directory and a file. ecab7a4204e3982963fb98fe978bb6c0514a4e19 Add new file. 61f6005706995d83937bf306b91a2842a93252ff Third commit a023684783cf46aeb35e896c58d5c3354505a5a3 Second commit. 1b1121e369013a0ae7efdd24e7bc851677489da7 First commit. % git checkout 71606375bdf3311583444f1adb72e54d52aaadfe -b before_removed % git branch * before_removed dev master % git log --pretty=oneline 71606375bdf3311583444f1adb72e54d52aaadfe (HEAD -> before_removed) Renamed and moved a directory and a file. ecab7a4204e3982963fb98fe978bb6c0514a4e19 Add new file. 61f6005706995d83937bf306b91a2842a93252ff Third commit a023684783cf46aeb35e896c58d5c3354505a5a3 Second commit. 1b1121e369013a0ae7efdd24e7bc851677489da7 First commit.
Gitコマンドまとめ_

参考リンク_
- サル先生のGit入門〜バージョン管理を使いこなそう〜
- まいなびWeb:2018年 バージョン管理システムトップ7 - Stack Overflow
- これでわかる!マイクロソフトがGitHubを買収する理由
Gitフロントエンドの使い方_
余裕がある場合はぜひGitHubの使い方も体験してみてください。埼玉大学工学部情報工学科3年次科目「実践的システム開発演習」ではGitHubを用いてチーム間での開発を行ってもらっています。