20190218のGitに関する記事は10件です。

Rails Herokuにpushで詰まった話

git push heroku masterで詰まった

今回は,Herokuにアップロードしようとした所で詰まったので記録しておきます。

$ git push heroku master
・
・
・
remote:  !     Push rejected, failed to compile Ruby app.
remote: 
remote:  !     Push failed
remote: Verifying deploy...
remote: 
remote: !       Push rejected to tranquil-wave-48446.
remote: 
To https://git.heroku.com/tranquil-wave-48446.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to・・・以下略
remote: -----> Ruby app detected
remote: 
remote:  !
remote:  !     You must use Bundler 2 or greater with this lockfile.
remote:  !

実行した所複数のエラーが発生し、何が原因化を模索・・・

pgの指定がおかしいのか、gemfile.lock、bundlerのバージョンが問題なのか調べても中々解決策が見つからない、わからない

bundler バージョンが問題?

自分の環境とHeroku上の環境でbundlerのバージョンが異なることによるエラーが原因(?)の様でした。

https://github.com/bundler/bundler/issues/6784

以上の記事を参考にさせていただきました。

$ heroku buildpacks:set https://github.com/bundler/heroku-buildpack-bundler2

を実行の後、再びHerokuへPushした所無事にアップロードができました!!!

感想

問題解決後にエラーを再検索してみると、同じ様なエラーになった人の記事がチラホラとありました。

もっと早い段階で気がつくことはできなかったのだろうか?
調べ方に改善の余地があるのかもしれない

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Gitでコンフリクトを発生させて、解消してみた。

環境

・Git version 2.20.1.windows.1

お題

今回はGitで発生しうるコンフリクト(競合)がどんなものか体験する。
まずは作業前にコンフリクトについてお勉強。

目次

1.競合って?
2.Gitにおけるコンフリクト(競合)とは?
3.ファイルの新規作成
4.リポジトリの初期化
5.TEST.txtを作成してcommitする。
6.トピックブランチAとBを作成する
7.トピックブランチAのTEST.txtを修正してコミットする。
8.トピックブランチBのTEST.txtを修正してコミットする。
9.コンフリクトを発生させて、解消する。

1.競合って?

そもそも競合ってなんだ。
と思ったわけではないが一応検索した。
結果、「互いにせりあうこと。」らしい。('ω')

2.Gitにおけるコンフリクト(競合)とは?

Gitにおける競合をコンフリクトと呼ぶらしい。

例えばmasterブランチにTEST.txtなるファイルを保持していたとする。

そのmasterブランチから、同じタイミングでトピックブランチAとBに派生させたときに
それぞれトピックブランチAではTEST.txtを

test1
test2

とする。

さて、トピックブランチBは

test3
test4

といった修正を加えたとする。

それぞれをmasterブランチにA、Bの順番でマージしようとする。
すると、Bをマージした時点で、コンフリクトが発生する。

同じ時点で別れたブランチで、別々の内容を持つTEST.txtファイルが
存在することになるので、正常にマージできず衝突してしまうようだ。

実際にmasterブランチでトピックブランチAとBをマージしようとすると、masterブランチのTEST.txtに競合を示す記述が記載される。
修正するには、作業者が内容に合わせてファイルを修正して、ステージ、コミットすれば良いことになる。

今回は一連の動作を実践してみることにした。

3.ファイルの新規作成

$ mkdir git-conflict
$ cd git-conflict/


4.リポジトリの初期化

$ git init
Initialized empty Git repository in C:/Users/local-pc/documents/work/git-conflict/.git/

5.TEST.txtを作成してcommitする。

$ touch TEST.txt

$ ls
TEST.txt

$ git add TEST.txt

$ git commit -m "first commit"
[master (root-commit) 8c1f140] first commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 TEST.txt

$ git status
On branch master
nothing to commit, working tree clean

6.トピックブランチAとBを作成する

$ git branch topicA

$ git branch topicB

$ git branch
* master
  topicA
  topicB

7.トピックブランチAのTEST.txtを修正してコミットする。

$ git checkout topicA
Switched to branch 'topicA'

(自分用に備忘:vimのペーストはInsertモードにしてからCTL + Insert、保存して終了はwq。)

$ git add TEST.txt
warning: LF will be replaced by CRLF in TEST.txt.
The file will have its original line endings in your working directory

$ git commit -m "topicA"
[topicA d35d541] topicA
 1 file changed, 2 insertions(+)

8.トピックブランチBのTEST.txtを修正してコミットする。

5と全く同じなので省略。
masterブランチをチェックアウトしておく。

$ git checkout master
Switched to branch 'master'

9.コンフリクトを発生させて、解消する。

まずはトピックブランチAをマージしてみる。

$ git merge --no-ff topicA
hint: Waiting for your editor to close the file...
[main 2019-02-18T13:20:51.237Z] update#setState idle
Merge made by the 'recursive' strategy.
 TEST.txt | 2 ++
 1 file changed, 2 insertions(+)

catでTEXT.txtの中身を除くと…

$ cat TEST.txt
test1
test2

うんうん。ちゃんと入ってる。

では今回の本題。
トピックブランチBをマージしてみる。

$ git merge --no-ff topicB
Auto-merging TEST.txt
CONFLICT (content): Merge conflict in TEST.txt
Automatic merge failed; fix conflicts and then commit the result.

無事(?)コンフリクト発生。

中身をのぞいてみる。

$ cat TEST.txt
<<<<<<< HEAD
test1
test2
=======
test3
test4
>>>>>>> topicB

こんな感じにGitが気を利かせて書き換えをしてくれている。
=======よりも上の行が現在のTEST.txtの内容で、つまりトピックブランチAの内容をマージした状態。
=======よりも下がトピックブランチBの内容を表している。
たぶん、このままaddしてcommitもできるんだろうけど、きちんと修正しとく。
修正した内容をcatする。

$ cat TEST.txt
test1
test2
test3
test4

これをadd、commitできれば、masterブランチで発生したコンフリクトを解消できたことになる。

$ git add TEST.txt
$ git commit -m "conflict clear!"
[master 653eba8] conflict clear!

ログをグラフでみるとこんな感じ。
うん。わかりにくい(´・ω・`)

$ git log --graph
*   commit 653eba813bfd6d0181463f769b6872c4bfbd6edf (HEAD -> master)
|\  Merge: 0d5193d 41afa16
| | Author: 僕の名前 <僕アドレス>
| | Date:   Mon Feb 18 22:28:32 2019 +0900
| |
| |     conflict clear!
| |
| * commit 41afa1692ddd5e251b816e2e2420f4f51bc80921 (topicB)
| | Author: 僕の名前 <僕アドレス>
| | Date:   Mon Feb 18 22:19:13 2019 +0900
| |
| |     topicB
| |
* |   commit 0d5193df3dfea53967673fe13477ffc541ce7645
|\ \  Merge: 8c1f140 d35d541
| |/  Author: 僕の名前 <僕アドレス>
|/|   Date:   Mon Feb 18 22:20:50 2019 +0900
| |
| |       Merge branch 'topicA'
| |
| * commit d35d541744457ed7b7f0f4df173b67db936e26f3 (topicA)
|/  Author: 僕の名前 <僕アドレス>
|   Date:   Mon Feb 18 22:17:03 2019 +0900
|
|       topicA
|
* commit 8c1f140cd4a3622ee1066f83b0900741eca35263
  Author: 僕の名前 <僕アドレス>
  Date:   Mon Feb 18 22:09:43 2019 +0900

      first commit
(END)

無事コンフリクトを解消できました。
慣れてしまえば以外と簡単ね。

今日はここまで!
明日はここで作ったファイルをGitHubのリモートリポジトリにpushしてみます。

こっからはJunitのお勉強だ(:3 」∠)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ローカル修正済みのファイルがリモートでフォルダ構成を移動されていた場合に対象ファイルを抽出する

ローカル修正済みの(pushしていない)ファイルがリモートでフォルダ構成を移動されていた場合に、ローカルの対象ファイルを抽出するコマンド

そんなことある??????と思われるかもしれないが、あった。

フォルダ構成を(git mvあるいはfilter-branchを使わずに)変更した場合はファイルが削除&追加されてしまう。そのままマージすると、同じファイルが(別の履歴・内容を持った状態で)2つ存在することになるはずである。従って、ローカルのコミットに含まれる当該ファイルを排除した状態でマージを実行したい。
普通にdiff --name-statusを取るとリモートで移動したファイルがすべて(DおよびAで)表示されてしまう。今回は変更ファイルが数百程存在したため諦めた。

欲しいものは、ローカルの変更ファイルとリモートの移動済みファイルの集合である。
順序はどちらでも良いが、今回はローカル側の変更ファイルの方が少なかったため「ローカルの変更ファイルのうち、移動済みだったものを探す」方向で考えた。

bash
$ git diff HEAD~..HEAD --name-only | xargs -n1 -I{} git diff --name-status --diff-filter=A origin/develop..HEAD {}

git diff <SHA1>..<SHA1> --name-onlyの標準出力をxargsコマンドによるパイプで繋いでorigin/developとのdiffに渡している。フィルダ構成が変わっている=gitは新ファイルとして認識しているので--diff-filter=Aで抽出している。diff--name-statusはdiff-filterと効果が被るが、分かり易さ優先で付けた。更にパイプで繋ぐ場合は--name-onlyにすると良いと思う。

出力
A       some/file/path/and/file_name.cpp
A       some/file/path/and/file_name.h
  ...以下差分ファイル一覧

今回は結局、ローカルのコミットが1つだけであり、さらに対象のファイルは2つだけだったため、一旦reset --soft HEAD~してからgit reset */file_name.*してコミットした。その後にマージしたりなんやかんやして、ローカルの変更をコピペで反映して事なきを得た。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[輪読] Pro Git 7.1章

背景

  • 弊ラボでは輪読と称して、技術書をまとめて発表する機会があるのですが、最近下書きでMarkdownで書き始めたこともあり、折角なのでQiitaにも投稿しておこうという所存です。
  • ラボでの公開が目的+Pukiwiki投稿のためインラインとかに関しては葛藤があり、あったりなかったりです...
  • 今回はProGitを読んでます。と言ってもProGitの内容は公式ページに日本語でも公開されており、内容もまとまっているので価値としては薄いかもしれません...
  • 意外と量がある+それぞれの関連性は薄いので細かく公開していこうかと

7. Git のさまざまなツール

本章

  • Gitの強力な機能を見ていく
  • 日々使うというよりは、知っておくと役立つこと

7.1 リビジョンの選択

  • 特定のリビジョンやコミットを参考にする方法はいくつかある

単一のリビジョン

  • ハッシュの指定で特定のコミットを参照にすることができる
  • 例えば、git logでcommitのハッシュ値を確認できる
❯ git log
commit ae621679a236564cf937256e4b275cba90399ac6 (HEAD -> master)
Author: pika1675@yahoo.co.jp <pika1675@yahoo.co.jp>
Date:   Fri Feb 15 18:30:41 2019 +0900

    change_to_helloworld

commit a8f67e8be00fb1043b7f03cdfb0fbb3107aad28e
Author: pika1675@yahoo.co.jp <pika1675@yahoo.co.jp>
Date:   Fri Feb 15 18:29:36 2019 +0900

    add_hello.py

commit 9c32e945a41bdef37b37ddaf5e476c251e9f33fc (origin/master, origin/HEAD)
Author: Pika <32129921+pikasigu@users.noreply.github.com>
Date:   Fri Feb 15 18:25:39 2019 +0900

    Initial commit
  • 特定のコミットを指定するにはコミットのハッシュ値を参考にすれば良い
  • ハッシュ値も全てではなく、4文字以上であれば特定は可能(一意であることはもちろん必要)
❯ git show 9c32e945a41bdef37b37ddaf5e476c251e9f33fc
commit 9c32e945a41bdef37b37ddaf5e476c251e9f33fc (origin/master, origin/HEAD)
Author: Pika <32129921+pikasigu@users.noreply.github.com>
Date:   Fri Feb 15 18:25:39 2019 +0900

    Initial commit

diff --git a/README.md b/README.md
new file mode 100644
index 0000000..21201ff
--- /dev/null
+++ b/README.md
@@ -0,0 +1,2 @@
+# ProGitTest
+Test repository for reading Pro Git

❯ git show 9c32
commit 9c32e945a41bdef37b37ddaf5e476c251e9f33fc (origin/master, origin/HEAD)
Author: Pika <32129921+pikasigu@users.noreply.github.com>
Date:   Fri Feb 15 18:25:39 2019 +0900

    Initial commit

diff --git a/README.md b/README.md
new file mode 100644
index 0000000..21201ff
--- /dev/null
+++ b/README.md
@@ -0,0 +1,2 @@
+# ProGitTest
+Test repository for reading Pro Git
  • git log に -abbrev-commit のオプションで一意に特定できる省略形で出力が可能
  • デフォルトは7文字だが、特定できない場合は長くなる
❯ git log --abbrev-commit --pretty=oneline
ae62167 (HEAD -> master) change_to_helloworld
a8f67e8 add_hello.py
9c32e94 (origin/master, origin/HEAD) Initial commit
  • 今回の場合はcommitが少ないのでデフォルトの7文字
  • まぁ、基本的にハッシュ値は被らないものとして考えても良い

ブランチの参照

  • 直感的にコミットを参照にしたい場合はコミットレベルというよりも、ブランチレベルの可能性もある
  • ブランチを参照することも可能
  • ブランチを指定するとブランチの最新のコミットが参照される
  • 適当にブランチを切って
❯ git checkout -b add_wiki_md_file
Switched to a new branch 'add_wiki_md_file'
  • 適当にコミットしてマージ
❯ git log
commit d2b51048ff55ba7faff617620fb5372a4ec193a5 (HEAD -> master, add_wiki_md_file)
Author: 飯尾直樹 <pika1675@yahoo.co.jp>
Date:   Fri Feb 15 19:08:32 2019 +0900

    wip_input_7.1

commit 129e7654eb17c61643c31257ad173185d5c059f9
Author: 飯尾直樹 <pika1675@yahoo.co.jp>
Date:   Fri Feb 15 19:02:37 2019 +0900

    create_md_file
  • ブランチを参照するのと、最新のコミットは同じ参照というのが確認できる
❯ git show d2b5104
commit d2b51048ff55ba7faff617620fb5372a4ec193a5 (HEAD -> master, add_wiki_md_file)
Author: 飯尾直樹 <pika1675@yahoo.co.jp>
Date:   Fri Feb 15 19:08:32 2019 +0900

    wip_input_7.1

diff --git a/wiki_reading.md b/wiki_reading.md
index e69de29..b227885 100644
--- a/wiki_reading.md
+++ b/wiki_reading.md

❯ git show add_wiki_md_file
commit d2b51048ff55ba7faff617620fb5372a4ec193a5 (HEAD -> master, add_wiki_md_file)
Author: 飯尾直樹 <pika1675@yahoo.co.jp>
Date:   Fri Feb 15 19:08:32 2019 +0900

    wip_input_7.1

diff --git a/wiki_reading.md b/wiki_reading.md
index e69de29..b227885 100644
--- a/wiki_reading.md
+++ b/wiki_reading.md
  • ブランチの指しているハッシュを探すには$git rev-parse
❯ git rev-parse add_wiki_md_file
d2b51048ff55ba7faff617620fb5372a4ec193a5
  • ブランチの最新のコミットを指しているのが確認できる

参照ログ(reflog)

  • Gitが裏でやっていることの1つ
  • HEADとブランチの参照がどう動いたかのログ
  • $git reflogで実行
❯ git reflog
d2b5104 (HEAD -> master, add_wiki_md_file) HEAD@{0}: merge add_wiki_md_file: Fast-forward
ae62167 HEAD@{1}: checkout: moving from add_wiki_md_file to master
d2b5104 (HEAD -> master, add_wiki_md_file) HEAD@{2}: commit: wip_input_7.1
129e765 HEAD@{3}: commit: create_md_file
ae62167 HEAD@{4}: checkout: moving from master to add_wiki_md_file
ae62167 HEAD@{5}: commit: change_to_helloworld
a8f67e8 HEAD@{6}: commit: add_hello.py
9c32e94 (origin/master, origin/HEAD) HEAD@{7}: clone: from https://github.com/pikasigu/ProGitTest.git
  • ブランチの先端(HEAD)更新のたびに情報が格納されている
  • このログから過去のコミットを指定することもできる
  • HEAD@{n}で参照
❯ git show 129e765
commit 129e7654eb17c61643c31257ad173185d5c059f9
Author: 飯尾直樹 <pika1675@yahoo.co.jp>
Date:   Fri Feb 15 19:02:37 2019 +0900

    create_md_file

diff --git a/wiki_reading.md b/wiki_reading.md
new file mode 100644
index 0000000..e69de29

❯ git show HEAD@{3}
commit 129e7654eb17c61643c31257ad173185d5c059f9
Author: 飯尾直樹 <pika1675@yahoo.co.jp>
Date:   Fri Feb 15 19:02:37 2019 +0900

    create_md_file

diff --git a/wiki_reading.md b/wiki_reading.md
new file mode 100644
index 0000000..e69de29
  • HEADの番号以外にも期間で遡った時のブランチの指定も確認できる
❯ git show master@{yesterday}
warning: Log for 'master' only goes back to Fri, 15 Feb 2019 18:25:57 +0900.
commit 9c32e945a41bdef37b37ddaf5e476c251e9f33fc (origin/master, origin/HEAD)
Author: Pika <32129921+pikasigu@users.noreply.github.com>
Date:   Fri Feb 15 18:25:39 2019 +0900

    Initial commit

diff --git a/README.md b/README.md
new file mode 100644
index 0000000..21201ff
--- /dev/null
+++ b/README.md
@@ -0,0 +1,2 @@
+# ProGitTest
+Test repository for reading Pro Git
  • このリポジトリ作成当日に前日のリポジトリを呼んだので、warningが出ている
  • 期間的に最も古いGitHubのinitの部分が呼ばれている
  • 参照ログが残っている期間は直近数ヶ月であり、それ以前のコミットに関しては使えない
  • $git log -ggit logっぽく出力できる
❯ git log -g master
commit d2b51048ff55ba7faff617620fb5372a4ec193a5 (HEAD -> master, add_wiki_md_file)
Reflog: master@{0} (飯尾直樹 <pika1675@yahoo.co.jp>)
Reflog message: merge add_wiki_md_file: Fast-forward
Author: 飯尾直樹 <pika1675@yahoo.co.jp>
Date:   Fri Feb 15 19:08:32 2019 +0900

    wip_input_7.1

commit ae621679a236564cf937256e4b275cba90399ac6
Reflog: master@{1} (pika1675@yahoo.co.jp <pika1675@yahoo.co.jp>)
Reflog message: commit: change_to_helloworld
Author: pika1675@yahoo.co.jp <pika1675@yahoo.co.jp>
Date:   Fri Feb 15 18:30:41 2019 +0900

    change_to_helloworld

commit a8f67e8be00fb1043b7f03cdfb0fbb3107aad28e
Reflog: master@{2} (pika1675@yahoo.co.jp <pika1675@yahoo.co.jp>)
Reflog message: commit: add_hello.py
Author: pika1675@yahoo.co.jp <pika1675@yahoo.co.jp>
Date:   Fri Feb 15 18:29:36 2019 +0900

    add_hello.py

commit 9c32e945a41bdef37b37ddaf5e476c251e9f33fc (origin/master, origin/HEAD)
Reflog: master@{3} (pika1675@yahoo.co.jp <pika1675@yahoo.co.jp>)
Reflog message: clone: from https://github.com/pikasigu/ProGitTest.git
Author: Pika <32129921+pikasigu@users.noreply.github.com>
Date:   Fri Feb 15 18:25:39 2019 +0900

    Initial commit
  • git logと比べるとreflogのデータも出力されている
  • あくまでmasterのログであるので、別ブランチのコミットは見ていない
❯ git log -g add_wiki_md_file
commit d2b51048ff55ba7faff617620fb5372a4ec193a5 (HEAD -> master, add_wiki_md_file)
Reflog: add_wiki_md_file@{0} (飯尾直樹 <pika1675@yahoo.co.jp>)
Reflog message: commit: wip_input_7.1
Author: 飯尾直樹 <pika1675@yahoo.co.jp>
Date:   Fri Feb 15 19:08:32 2019 +0900

    wip_input_7.1

commit 129e7654eb17c61643c31257ad173185d5c059f9
Reflog: add_wiki_md_file@{1} (飯尾直樹 <pika1675@yahoo.co.jp>)
Reflog message: commit: create_md_file
Author: 飯尾直樹 <pika1675@yahoo.co.jp>
Date:   Fri Feb 15 19:02:37 2019 +0900

    create_md_file

commit ae621679a236564cf937256e4b275cba90399ac6
Reflog: add_wiki_md_file@{2} (飯尾直樹 <pika1675@yahoo.co.jp>)
Reflog message: branch: Created from HEAD
Author: pika1675@yahoo.co.jp <pika1675@yahoo.co.jp>
Date:   Fri Feb 15 18:30:41 2019 +0900

    change_to_helloworld
  • ブランチも見るとわかりやすい
  • 参照ログは完全にローカルなログ
  • クローンした時の参照ログは空
  • 試しにそれなりに色々しているリポジトリ(卒論の手書きのやつ)をクローンしてみる
❯ git clone https://github.com/pikasigu/Tegaki.git
Cloning into 'Tegaki'...
remote: Enumerating objects: 157, done.
remote: Total 157 (delta 0), reused 0 (delta 0), pack-reused 157
Receiving objects: 100% (157/157), 5.41 MiB | 3.32 MiB/s, done.
Resolving deltas: 100% (93/93), done.

❯ git log -g master
commit cb5245e21feec1b70df373c2bd8e95a8a9a99ab1 (HEAD -> master, origin/master, origin/HEAD)
Reflog: master@{0} (飯尾直樹 <pika1675@yahoo.co.jp>)
Reflog message: clone: from https://github.com/pikasigu/Tegaki.git
Author: Pika <32129921+pikasigu@users.noreply.github.com>
Date:   Tue Nov 20 18:12:25 2018 +0900

    Create Readme
  • 最新のコミットだけになっている

家系の参照

  • コミットの特定に使われやすいのは家系から辿っていく方法
  • 参照の最後に~をつけることで、それをコミットの親とする
❯ git log --pretty=format:'%h %s' --graph
* d2b5104 wip_input_7.1
* 129e765 create_md_file
* ae62167 change_to_helloworld
* a8f67e8 add_hello.py
* 9c32e94 Initial commit
  • fast-forwardだったので分岐感がないですね...
❯ git show HEAD~
commit 129e7654eb17c61643c31257ad173185d5c059f9
Author: 飯尾直樹 <pika1675@yahoo.co.jp>
Date:   Fri Feb 15 19:02:37 2019 +0900

    create_md_file

diff --git a/wiki_reading.md b/wiki_reading.md
new file mode 100644
index 0000000..e69de29
  • 折角なので卒論の方のgit logも
❯ git log --pretty=format:'%h %s' --graph
* cb5245e Create Readme
* dbabd26 OC opt dic
*   33b3e93 Merge branch 'change_DB_alg'
|\
| * 0fc3006 optimize sp
| * c1f2728 optimize server
| * 87b4cd7 del_log
| * dfbc600 fix some
|/
* d6d839e bug fix
*   4245f39 Merge branch 'add_DB_GUI'
|\
| * 8de62f6 delete log
* |   01e4ed1 Merge branch 'add_DB_GUI'
|\ \
| |/
| * 97830b1 post_DB deleteFLG
| * 7670643 add_getDB
|/
*   056d854 Merge branch 'new-branch-name'
|\
| * e6abcef ver1.0
| * 97ece8d 評価実験直前修正
| * 8c00897 add particle & pos
| * 98415f5 textarea + copy
| * b0aa0fc 辞書追加修正
| * 74969a7 改造前ver
| * dda674b 辞書機能完成(β)
| * 7f0f6ef 不安定ver
|/
* ddf78cc parsererror
* 36a9602 php+sqlを追加
* 0ffe1f8 no message
* 150a626 基本動作初期
  • 管理が汚くてあれですが...
  • 8de62f6 delete logのコミットの親を見てみると
❯ git show 8de62f6~
commit 97830b1a25ccb6752478fe5795e1887646ea8f3d
Author: naoki <pika1675@yahoo.co.jp>
Date:   Tue May 15 03:24:12 2018 +0900

    post_DB deleteFLG

diff --git a/DB-index.html b/DB-index.html
index 109af79..299485d 100644
--- a/DB-index.html
+++ b/DB-index.html
  • 時間的に直前の01e4ed1ではなくて、ちゃんと親の97830b1を見ていますね
  • ちなみに~~や~2の様に書くことで親の親の様な参照もできます
  • ^でも少し違った親の参照の仕方で同様の参照をするようですが、自分の環境で動作しなかったので今回は省略します

コミットの時範囲指定

  • ここのコミットの指定ではなく、コミットの範囲指定を考える
  • 使うイメージはメインのブランチにマージしていないのはどのブランチだっけという状態の時

  • ダブルドット構文というのがあり、片方のコミットからは辿れるけれども、もう片方は辿れないという状況のことらしい
    7.1

  • 上の図で言うとmasterブランチとexperimentブランチでブランチが切られています

  • masterブランチからみるとexperimentブランチにコミットされたC,Dブランチは見えません

  • そういうコミットをたどるにはmaster..experimentのように支持することでコミットを参照することができます

  • 構文としては(あるブランチから見た)..(あるブランチの辿れない範囲)みたいな感じです

$git log master..experiment
D
C
  • 逆にすればA,Bが出力されます

  • つまり、masterからこれらのようにブランチを指定することでmasterにマージされていないコミットを知ることができるというわけですね

  • もう1つの使い方として、origin/master..HEADのように見ることでこれからpushするコミットを確認するという使い方もあります

❯ git log origin/master..HEAD
commit d2b51048ff55ba7faff617620fb5372a4ec193a5 (HEAD -> master, add_wiki_md_file)
Author: 飯尾直樹 <pika1675@yahoo.co.jp>
Date:   Fri Feb 15 19:08:32 2019 +0900


    wip_input_7.1

commit 129e7654eb17c61643c31257ad173185d5c059f9
Author: 飯尾直樹 <pika1675@yahoo.co.jp>
Date:   Fri Feb 15 19:02:37 2019 +0900

    create_md_file

commit ae621679a236564cf937256e4b275cba90399ac6
Author: pika1675@yahoo.co.jp <pika1675@yahoo.co.jp>
Date:   Fri Feb 15 18:30:41 2019 +0900

    change_to_helloworld

commit a8f67e8be00fb1043b7f03cdfb0fbb3107aad28e
Author: pika1675@yahoo.co.jp <pika1675@yahoo.co.jp>
Date:   Fri Feb 15 18:29:36 2019 +0900

    add_hello.py

  • pushしていないclone後のコミットが出力されています
  • このダブルドット構文は片方を省略することが可能で、省略した場合はそこがHEADとして考えられます
  • ダブルドット構文以外にも同様の意味を持つ表現は可能です
$ git log refA..refB
$ git log ^refA refB
$ git log refB --not refA
  • ダブルドットはできませんが、他の表現だと3つ以上の参照を考えられます
$ git log refA refB ^refC
$ git log refA refB --not refC
  • 2つは同じ意味で、A,Bからは辿れるけれど、Cからは辿れないコミットを参照します
  • トリプルドット構文も実はあり、トリプルドットは片方どちらかにのみ辿れるコミットを参照します
$ git log master...experiment
F
E
D
C
  • A,Bはどちらのブランチからでも参照できるので、含まれません
  • このlog出力には--left-rightオプションをつけることで、どちらのブランチに含まれるコミットかを表示してくれます
$ git log --left-right master...experiment
< F
< E
> D
> C

まとめ

  • ブランチ参照はハッシュ参照くらいしか知らなかったですね
  • 範囲指定とか使い所はありそうですが、実際的確に使えるかというと難しそうです...

  • 続き

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

git diffの全オプション一覧

GitのサイトにはPro Git 2nd ed. Editionという本が全文無償公開されていて、日本語訳も公開されています。
なのでGitの使い方についてはこの本を読めば概ね事足ります。
ちなみに最新版はGitHubにあります。

それはいいのですが、なにげに意外なことにリファレンスは日本語訳が、というか英語以外の言語がないみたいです。

以下は、諸事情でgit diff --break-rewritesについて知りたかったのだけど日本語解説が一件たりとも存在しなかったので調べたついでに全オプションについて軽く調べてみたメモです。
マニュアルのバージョンは2.20.0

git diff

SYNOPSIS

書式。
基本的にgit diff、オプション、対象コミット、--、対象ファイル名の順に書く。

git diff [<options>] [<commit>] [--] [<path>…​]
git diff [<options>] --cached [<commit>] [--] [<path>…​]
git diff [<options>] <commit> <commit> [--] [<path>…​]
git diff [<options>] <blob> <blob>
git diff [<options>] --no-index [--] <path> <path>

DESCRIPTION

git diff [<options>] [--] [<path>…​]

最新インデックスから現在までの差分を表示する。
addするとインデックスが更新されるので出てこなくなる。

git diff [<options>] --no-index [--] <path> <path>

Git管理外のファイルも--no-indexを付ければ対象にできる。
付けなければGit管理下にあるファイルのみが対象となる。

git diff [<options>] --cached [<commit>] [--] [<path>…​]

最新コミットから最新インデックスまでの差分を表示する。
要するに最後のaddまでの差分。addした後の変更は出てこない。
--stagedも同じ。

git diff [<options>] <commit> [--] [<path>…​]

現在のブランチ(HEAD)と指定のコミットとの差分を比較する。

git diff [<options>] <commit> <commit> [--] [<path>…​]

指定のふたつのコミットの差分を比較する。
片方を省略するとHEADを指定したものとなる(上と同じ)。

git diff [<options>] <commit>..<commit> [--] [<path>…​]

スペース区切りと同じ。
片方省略もできる。

git diff [<options>] <commit>...<commit> [--] [<path>…​]

指定のふたつのコミットについて、共通の祖先まで遡ってそこから後者への差分を比較する。
言葉だとわかりにくいが、画像を見れば一発だろう。

01.png
画像はWhat are the differences between double-dot ".." and triple-dot "..." in Git diff commit ranges?より拝借。

git diff [<options>] <blob> <blob>

コミットではなくBLOBオブジェクト同士の差分を比較する。

オプション一覧

-p

-u

--patch

パッチを作成する。デフォルトの動作。

-s

--no-patch

差分を標準出力に出さないようにする。
git showなどと一緒に使うとよいが、git diffに使うと何も出ない。

-U<n>

--unified=<n>

変更された行の前後に出力する、変更されていない行の行数を変更する。
デフォルト3。
0にすると変更された行しか出さない。

--raw

diffをRawフォーマットで出力する。
RawフォーマットはGitの内部形式らしい。

--patch-with-raw

-p --rawと同じ。
なのだが、-p --rawより長い。

--indent-heuristic

意図しているだろう感じで差分がうまく出るよう判定を改善する
デフォルトでオン。

--no-indent-heuristic

--indent-heuristicを使わない。

--minimal

できるだけ差分が少なくなるように比較する。
そのぶん処理に時間がかかる。

--patience

patience diffアルゴリズムを使って差分を生成する。

--histogram

histogram diffアルゴリズムを使って差分を生成する。

--anchored=<text>

anchored diffアルゴリズムを使って差分を生成する。
ということらしいのだが結果を見てもよくわからない。

--diff-algorithm={patience|minimal|histogram|myers}

任意のアルゴリズムを使って差分を生成する。
値を指定しない場合はmyersが使われる。
値を--diff-algorithm=defaultとすると、設定ファイルに書かれているdiff.algorithmが使われる。

--stat[=<width>[,<name-width>[,<count>]]]

diffstat形式で出力する。diffstatは↓のような形式。

  path/to/hoge,html     | 5000 +++--
  path/to/fuga,html     | 1234 -------

カンマ区切りで3つまで指定可能な引数で出力範囲を指定できる。
第1引数widthは全体の横幅。
第2引数name-widthはそのうちファイル名部分の横幅。
第3引数countは行数。指定行数を超えるとそれ以降は省略される。

--stat-width=<width>

--stat-name-width=<name-width>

--stat-count=<count>

↑の--statをそれぞれ個別に設定する。

--compact-summary

diffstat形式に、ファイル作成・削除などのサマリを追加表示する。
new、gone、+l(シンボリックリンク)、+x(実行権限追加)など。
表示内容はstatのファイル名とグラフの間に出力される。

--numstat

statと似ているがより省力で、追加行数、削除行数、ファイルパスだけを出力する。

100 50 path/to/hoge,html

--shortstat

statの最後の行、変更されたファイル数、追加行数、削除行数の合計だけを出力する。

999 files changed, 765 insertions(+), 573 deletions(-)

--dirstat[=<param1,param2,…​>]

ファイルの差分がどのディレクトリに多いかをパーセンテージで表示する。
ディレクトリ内のファイルが変更された割合ではない。

パラメータをカンマ区切りで追加することで動作を変更できる。例:git diff --dirstat=files,10,cumulative
changesはコードの移動はカウントせず、追加削除された行のみを計算する。
linesは行数でカウントする。通常のカウント。
filesは変更されたファイル数をカウントする。中身は見ない。
cumulativeはサブディレクトリも集計に入れる。合計は100%を超える。
数値は足切り。それ以下のディレクトリは親にまとめられる。

--summary

ファイル追加削除、権限変更など拡張ヘッダ情報のみを表示する。

--patch-with-stat

-p --statと同じ。
-p --statより長い。

-z

--name-only--numstatなどと一緒に使うと、区切りが改行ではなくNULになる。
--statなどには効かない。

--name-only

変更されたファイル名のみを表示する。

--name-status

変更されたファイル名とステータスを表示する。

--submodule[=<format>]

サブモジュールのdiffの表示形式を指定する。
shortはサブモジュール内のcommitは最初と最後しか表示しない。
logはサブモジュール内のcommitを全て一覧表示する。
diffは普通にdiffを表示する。

--color[=<when>]

カラー表示をどうするか指定する。
デフォルト設定はcolor.uiおよびcolor.diffで変更できる。

alwaysはdiffをカラー表示する。
neverは必ず白黒表示する。
autoはよくわからない。

--no-color

--color=neverと同じ。

--color-moved[=<mode>]

移動したコードの色をどうするか指定する。
指定可能な値はnodefaultzebraplainblocksdimmed-zebra

--color-moved-ws=<modes>

--color-movedを検出する際に空白を取り扱う方法を指定する。
デフォルト設定はdiff.colorMovedWSで変更できる。

ignore-space-at-eolは改行を無視する。
ignore-space-changeはスペースの量の変化を無視する。スペース数0→1や1→0は検出するが1→10などは無視。
ignore-all-spaceはスペースの変化を完全に無視する。
allow-indentation-changeは、スペースの変化量が全て同じブロックをグループ化する。

--word-diff[=<mode>]

行単位ではなくワード単位でdiffを表示する。

colorは色だけで表示する。コピペすると区切りがわからなくなる。
plainは追加を{+ +}で、削除を[- -]で括って表示する。中のテキストをエスケープしないので、同じ文字が入っていると区切りがわからなくなる。
porcelainは区切りを改行で表す。元々の改行は~で表す。正直わかりにくい。
noneは何もしない、未指定と同じ。

--word-diff-regex=<regex>

ワード単位でdiffを表示する際のワードの区切りを正規表現で指定する。

--color-words[=<regex>]

--word-diff=color -word-diff-regexと同じ。

--no-renames

ファイル名を変更しただけのファイルは検出しない。

--check

スペースの次にタブ、および末尾スペースがあったときに警告メッセージを出す。
動作はcore.whitespaceで変更できる。

--ws-error-highlight=<kind>

行末の空白をエラー表示するか否か。引数は,区切りで複数指定可能。
oldは変更前をエラーとして表示する。
newは変更後をエラーとして表示する。
allold,new,contextに同じ。
表示色はcolor.diff.whitespaceで設定する。

--full-index

commitハッシュを省略形ではなくフル表示する。

--binary

--full-indexに加え、git applyで使えるバイナリのdiffも出力する。
と書いてあるのだが手元では--full-indexの効果はなかった。

--abbrev[=<n>]

diff --rawなどに出力するハッシュの桁数を指定する。

-B[<n>][/<m>]

--break-rewrites[=[<n>][/<m>]]

diffを書き換えではなく、削除と挿入のペアとして表す。
引数を-B/70%とか-B100%/0%のように渡すことで、ファイルが編集ではなく完全な書き換えと判断する基準を変更することができる。
となっているみたいなのだが正直よくわからなかった。

-M[<n>]

--find-renames[=<n>]

リネームを検出する。
-M90%とすると、中身の90%以上が同じファイルは削除+追加ではなく名前変更とみなす。
デフォルトは50%。

-C[<n>]

--find-copies[=<n>]

コピーを検出する。
オプションの指定方法はリネームと同じ。
コピー元の候補になるのは、中身が変更されたファイルのみ。

--find-copies-harder

--find-copiesと同じだが、全てのファイルをコピー元の候補として調べる。
そのためとても重い。

-D

--irreversible-delete

削除されたファイルは差分を表示しない。

-l<num>

-Mおよび-Cを使用した際、この制限を超えたら処理を打ち切る。
理由としてはそれらの処理時間がO(n^2)オーダーであるため。

--diff-filter=[(A|C|D|M|R|T|U|X|B)…​[*]]

diffの出力をフィルタリングする。
Aは追加されたファイルのみ、Dは削除されたファイルのみ、Cはコピーされたファイルのみ、Rはリネームされたファイルのみ、Mは変更されたファイルのみ。
TUXBはサブモジュールなど。
複数のオプションを--diff-filter=ACDMのように指定可能。
*を入れると、該当の差分がないときは何も表示せず、該当の差分があれば全ての差分を表示する。

小文字にすると逆になる。
--diff-filter=aであれば追加された以外の変更があったファイルを全て検出する。

-S<string>

差分で引数の文字の出現回数が変更されたファイルを検出する。
-f"hoge"とすると、hogeの出現回数が変わったファイルを差分出力する。
100行目でhogeを追加し、200行目から削除したような場合は出力されない。

-G<regex>

差分で引数の文字が出現したファイルを検出する。
文字列には正規表現を使用可能。
100行目でhogeを追加し、200行目から削除した場合でも出力される。

--find-object=<object-id>

指定のオブジェクトの出現回数が変更されたファイルを検出する。
使い方は-Sと同じ。

--pickaxe-all

-S-Gにおいて、ひとつでも変更が見つかったら全ファイルの差分を表示する。

--pickaxe-regex

-Sにおいて正規表現を使えるようになる。

-O<orderfile>

diffの出力ファイルの順番を、引数のファイルの設定に変更する。
ファイルの書式はfnmatch.gitignoreと同じ。
引っかかった上から順に表示するとなっているのだが、手元ではどうやっても順番が変わらなかった。

-R

diffの元ブランチと先ブランチを入れ替える。
つまりdiff AAAAAA BBBBBBdiff -R BBBBBB AAAAAAは同じ。

--relative[=<path>]

--relativeだけだと、サブディレクトリからdiffを実行した際にカレントディレクトリ以下のファイルしか見ない。
--relative="foo/bar/"とすると、foo/bar/ディレクトリでdiff --relativeを実行したかのような出力になる。
サブディレクトリから実行する場合でも、パスの指定はgitルートからの指定になる。

-a

--text

全てのファイルをテキストファイルとみなして扱う。

--ignore-cr-at-eol

改行の前にあるCRを無視する。

--ignore-space-at-eol

改行の前にあるスペースを無視する。

-b

--ignore-space-change

スペースの個数だけの変更は無視する。
0から1になった、1から0になった場合は無視しない。
functionfunc tionは無視しない。

-w

--ignore-all-space

0から1を含め、あらゆるスペースの変更を無視する。
functionfunc tionでも無視される。

--ignore-blank-lines

空行のみの追加削除を無視する。
空行以外の変更があった場合は無視しない。

--inter-hunk-context=<lines>

1ファイルに変更箇所が複数ある場合、デフォルトでは8行くらい離れているとdiff出力が別に分かれる。
この数値を大きくすると、離れた行もひとつの変更とみなす。

-W

--function-context

変更があったファイルは全てを表示する。

--exit-code

差分があれば終了ステータス1、なければ終了ステータス0で終了する。

--quiet

標準出力しない。--exit-codeを含む。

--ext-diff

外部diffヘルパーを使用する。
ということらしいが実際はgit config等で指定が必要なので、単に↓と揃えただけと思われる。

--no-ext-diff

外部diffヘルパーを使用しない。
デフォルトで外部diffヘルパーを使っている場合にそれをキャンセルする。

--textconv

--no-textconv

バイナリファイルのテキスト変換フィルタを指定している場合に、それを使って差分を表示する、もしくは使用しないでバイナリのまま比較する。

--ignore-submodules[=<when>]

サブモジュールへの変更をどうするか。
noneはサブモジュールの変更を全て取得する。
untrackedは、変更は追跡する、新規ファイルは追跡しない。
dirtyはサブモジュールで管理されているファイルは無視され、親プロジェクトで管理されているファイルは追跡する。
allはサブモジュール内の変更は全て無視する。
デフォルトはall。1.7.0まではdirty

--src-prefix=<prefix>

変更元ファイルのプレフィックスをa/ではなく指定した値にする。

--dst-prefix=<prefix>

変更後ファイルのプレフィックスをb/ではなく指定した値にする。

--no-prefix

両方のファイルからプレフィックスを表示しない。

--line-prefix=<prefix>

出力の全行にこのプレフィックスを表示する。

--ita-invisible-in-index

--ita-visible-in-index

git add -Nで追加したファイルは、git diffでは登録済みの空ファイルとして、git diff --cachedでは未登録のファイルとして表示される。
--ita-invisible-in-indexオプションを入れるとgit diffでは未登録の新規ファイルとして表示し、git diff --cachedでは何も出てこない。
--ita-visible-in-indexは未指定と同じ。

-1 --base

-2 --ours

-3 --theirs

merge時のコンフリクトなど、3状態を比較する際に使用する。

-o

マージされていないエントリについては出力を省略して、単にUnmergedとだけ出す。

<path>…

パスを与えると、そのディレクトリ以下のファイルに対してのみdiffを実行する。

感想

なんだこりゃ。

何も考えず節操なく付け加えていった結果にしか見えない、

指定しても出力が変わらなくて何を意味するのか全くわからないオプションとかあって、少し整理したほうがいい気がする。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Gitのコミット数と行数を確認する

Gitで自分のコミット数を計測したいときありますよね。
そんなときに使ったコマンドを残しておきます。
私のGitのアカウントは、noracornなのでそこは読み替えてください。

全体のコミット数を確認するコマンド

リポジトリ内に移動して打ってください。

git log --date=iso --pretty=format:"[%ad] %h %an : %s" | grep  "noracorn :" | wc -l

月ごとのコミットを見るコマンド

git log --date=iso --pretty=format:"[%ad] %h %an : %s" | grep  "noracorn :" | grep 2019-01 | wc -l

修正した行数を見るコマンド(合計行数、追加行数、削除行数)

git log --numstat --pretty="%H" --author='noracorn' --since=2013-01-11 --until=2019-01-01 --no-merges | awk 'NF==3 {plus+=$1; minus+=$2} END {printf("%d (+%d, -%d)\n", plus+minus, plus, minus)}'
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Gitで一つ前にチェックアウトしていたブランチに移動する`git checkout -`というコマンドに感動したお話

背景

最新のmasterを開発中のブランチに取り込んだり、他の人が開発中のブランチを取得する時、一度ブランチをチェックアウトしてすぐ元の作業ブランチに戻る、といった事をすることがあるかと思います。
私は今までgit checkout mastergit pull origin mastergit checkout my_branchgit merge masterとしていました。
そして、開発中のブランチ名ってなんだったっけ・・?えーと・・・あ、これこれ。となっていたのです。

git checkout -

一つ前のディレクトリに戻るcd -コマンドのように、一つ前にチェックアウトしていたブランチに移動するgit checkout -というコマンドが存在することを10分前に初めて知りました。
上記のコマンドが以下のようになります。
git checkout mastergit pull origin mastergit checkout -git merge master

何が嬉しいのか

「開発中のブランチ名を確認する」という小さなタスクの存在がなくなりました。
こういう小さなワンアクションが消える事に喜びを感じるマンなので軽いパラダイムシフトですね。

みなさんもgit checkout -で良いGitライフを!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ポータブル環境でVSCodeからGitHubプライベートリポジトリを使う

ポータブル環境でVSCodeからGitHubプライベートリポジトリを使う

【ぜんぶポータブル】ポータル

最終更新:2019年2月22日 Mac VMware上での動作状況を追記しました

このドキュメントは、ワクワクしながらVSCodeからGitHubのプライベートリポジトリを使おうとして、

2019-02-18-10-35-43.png

とか、

2019-02-18-10-33-05.png

の悪夢に悩まされている方向けです。それズバリ認証失敗です。

スマートな解決策が他にあるかもしれませんが、僕が色々試したところでは、どうしても/dev/tty問題が解決できず、VSCodeのパスフレーズ入力ダイアログを回避してssh-agentに認証を任せるしかありませんでした。ここではその手法を説明します。

構築に使用した環境

  • Windows10 Version 1803
  • Visual Studio Code 1.31.0 zip版
  • (Portable)Git for Windows 2.20.1
  • ポータブル環境ではないVSCodeとGitもインストールされている(がこちらは使わない)
  • ポータブル環境は以下の様にVSCodeとPortableGitが展開されている
[jtHiuPortable]
├───[apps]
│   └───[win]
│       ├───[VSCode]
│       ├───[PortableGit]
│       └───Code.cmd
├───[files]
└───VSCode_Win.lnk
コマンドプロンプト
> echo start %~dp0VSCode\Code.exe > Code.cmd

ここまでで「えぇっと…」と思った方は、このページではなくステップバイステップの方で進めてください。

確認済みの事項

  • ○ Windows7での動作を確認しました。
  • ○ ネットワークドライブ(情報大のZ:ドライブ)での動作を確認しました。
  • ○ OneDrive上での動作を確認しました。
  • × パス中に日本語フォルダ名を含むとダメです。
  • × UNCパスもダメです。
    • Windowsエクスプローラーのホーム→新規→ショートカット→「ドライブとしてマップ」からドライブレターを割り当ててください。
  • × Mac上VMwareのvmware-host経由では、ドライブとしてマップでもダメでした。
    • デバイスごとWindowsに接続している場合は大丈夫です。OneDriveもOK。ただし、なぜかVSCode起動用バッチのコマンドプロンプトが終了しませんので、気にしないのが吉です。

ポータブル環境用Gitの使用を明示する

デフォルトでは当然、マシンにインストールされているGitを使いに行こうとしますが、まずはこれをポータブル環境へ引き込むためにパスなどの環境変数を設定するバッチファイルを作成します。

コマンドプロンプト
D:\jtHiuPortable> touch apps\win\setPath.cmd
setPath.cmd
@echo off
if Defined AppsWinRoot GoTo PostPathSettings
echo Portable Console is preparing environment variables.
set NOW_CD=%cd%
cd /D %~dp0..\..
set HOME=%cd%
cd /D %NOW_CD%
set AppsWinRoot=%HOME%\apps\win
set GitD=%AppsWinRoot%\PortableGit
set PATH=%GitD%\cmd;%GitD%;%GitD%\usr\bin;%path%
:PostPathSettings
echo Portable home has located in %HOME%
echo Portable applications have located in %AppsWinRoot%

要点解説:

  • 2行目 … 多重起動によるPATH登録の無限増殖を防いでいます。
  • %~dp0 … 「動作中のスクリプトファイルがあるパス」です。
  • 環境変数HOMEの設定 … sshなどMSYS2(MinGW64)なコマンドは環境変数HOMEをホームディレクトリとして使用します。環境変数に相対パスの部分を残したくなかったので、ちょっと面倒な手順を踏んで設定しています。
  • PATHへの追加項目
    • %GitD%\cmd … git起動用
    • %GitD% … git-bash起動用
    • %GitD%\usr\bin … MSYS2(MinGW64)各種コマンド向け

これを、きちんとポータブル環境で動作しているか確認するため、あえて標準のホームから叩いてみます。sshはもちろん接続にコケますが、ポータブル環境のホームに.sshフォルダが自動的に作成されたことを確認してください。

コマンドプロンプト
Microsoft Windows [Version 10.0.17134.590]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Users\MyName>D:\jtHiuPortable\apps\win\setPath.cmd
Portable Console is preparing environment variables.
Portable home has located in D:\jtHiuPortable
Portable applications have located in D:\jtHiuPortable\apps\win

C:\Users\MyName>git --version
git version 2.20.1.windows.1

C:\Users\MyName>git-bash
(git-bashのウィンドウが開く)

C:\Users\Nyname>ssh -T git@github.com
The authenticity of host 'github.com (192.30.255.113)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to continue connecting (yes/no)?
(とりあえず空Enter)
Host key verification failed.
MINGW64:/c/Users/MyName
MyName@MyWin MINGW64 /c/Users/MyName
$ ls ~
apps/ files/ VSCode_Win.lnk

これで、gitやsshが起動することと、git-bash上でホームディレクトリがきちんとポータブル環境のフォルダになっていることを確認できました。

apps\winにあるVSCode起動用バッチファイルも、これを経由するようにします。

Code.cmd
@echo off
call %~dp0setPath.cmd
start %~dp0VSCode\Code.exe

VSCodeのGit自動検索を回避する

VSCodeは起動時に、標準的なGit for Windowsのインストール場所を巡回して探してくるというポータブル環境にとっては大変余計なことをしてくれます。そんな訳で仕方なくsettings.jsongit.pathにフルパス書くんですが汎用性が低い。なんで、これでいいです。てか、こう書いてください。

settings.json
{
    "git.path": "git"
}

セキュリティリスクは判るけどこれをデフォルトにしてくれよ…とも思うんですが… こうするとパスの通ったGit環境を使ってくれます。もちろん既に色々設定している方は、この一行(と行末にコンマも付けて)追加してください。ちなみにsettings.jsonCtrl+Shift+Pでコマンドパレットを開いて、open settings (jぐらいまで打てば開けます。

ポータブル環境向けのSSHキーを作成し登録する

既にSSHキーをお持ちの方も多いとは思いますが、ポータブルデバイス紛失のリスクを考えると、大事な秘密鍵を持ち歩きたくはありませんので、ポータブル用のキーペアを新たに作成する方が安心です。フォーマットはGitHubの流儀に従って作成します。メールアドレスは自分のものに変更します。-fオプションで保存先とキーペアの名前も指定します。

コマンドプロンプト
> ssh-keygen -t rsa -b 4096 -C "j-t@s.do-johodai.ac.jp" -f %HOME%\.ssh\rsa_GitHub_HIU
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
(パスフレーズ(パスワード)を入力する)
Enter same passphrase again:
(パスフレーズを再入力する)
Your identification has been saved in D:\jtHiuPortable\.ssh\rsa_GitHub_HIU.
Your public key has been saved in D:\jtHiuPortable\.ssh\rsa_GitHub_HIU.pub.
The key fingerprint is:
SHA256:~~~~~~ j-t@s.do-johodai.ac.jp
The key's randomart image is:
+---[RSA 4096]----+
|  ステキなアート  |
+----[SHA256]-----+

> clip < %HOME%\.ssh\rsa_GitHub_HIU.pub

最後の1行は、GitHubの流儀にもある、生成した公開鍵をクリップボードにコピーするためのものです。これに従って、自分の公開鍵を登録します。
2019-02-18-13-54-24.png
GitHubの画面右上の自分のアイコンからsettingsを選び、
2019-02-18-13-58-28.png
サイドバーのSSH and GPG Keysを選択して、右上の方のNew SSH keyボタンを押して、
2019-02-18-14-02-23.png
Titleには、複数のキーを登録した時に自分で区別が付けられるような名前を入力し、Key欄でCtrl+Vで貼り付けたら、Add SSH keyボタンを押します。
2019-02-18-14-04-25.png
パスワードを聞かれたら(鍵生成時に入力したパスフレーズではなく)GitHubアカウントのパスワードを入力してConfirm passwordボタンを押して完了です。
2019-02-18-14-07-12.png
これでGitHubにSSH接続するためのキーを登録することが出来ました。2

SSH・Gitの設定をする

GitHub向けのSSH接続設定を、ポータブル環境フォルダ直下に作成された.sshの下にconfigというファイルを作成して書きこみます。Usergit固定です、書き換えないように注意してください。IdentityFileは作成したキーペアへのパスです。ここはUnixスタイルのパス表記になります。

config
Host github.com
  User git
  Hostname github.com
  IdentityFile ~/.ssh/rsa_GitHub_HIU
  IdentitiesOnly yes

次に、Gitでのコミットをサインオフするためのユーザ名とパスワードを設定します。もちろん自分のものに変更して入力してください。詐称はいやん。

コマンドプロンプト
> git config --global user.name "TANAHASHI, Jiro"

> git config --global user.email "j-t@s.do-johodai.ac.jp"

エラーも何も表示されなければ成功です。ポータブル環境のホームに.gitconfigファイルの作成が確認できます。

それではアクセスチェックです。

コマンドプロンプト
> 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.
Are you sure you want to continue connecting (yes/no)?
(Enterキーではなく、「yes」としっかり入力する)
Warning: Permanently added 'github.com,192.30.255.112' (RSA) to the list of known hosts.
Enter passphrase for key '/d/jtHiuPortable/.ssh/rsa_GitHub_HIU':
Hi jtFuruhata-HIU! You've successfully authenticated, but GitHub does not provide shell access.

みたいに、You've successfully authenticatedって言われたら、ここまでの手順はOKです。known_hosts.sshに自動的に作成され、ここまでのフォルダ構造を確認すると以下の様な感じです。

[jtHiuPortable]
├───[.ssh]
│       ├───config
│       ├───known_hosts
│       ├───rsa_GitHub_HIU
│       └───rsa_GitHub_HIU.pub
├───[apps]
│   └───[win]
│       ├───[VSCode]
│       ├───[PortableGit]
│       ├───Code.cmd
│       └───setPath.cmd
├───[files]
├───.bash_history   //もちろんこれはなくてもいい
├───.gitconfig
└───VSCode_Win.lnk

ssh-agentを起動する

これでOKなはずなんですけどどうにもパスワードを聞いてくれない。そこでssh -vとか色々とデバッグログを見ていると、きちんとポータブル環境のファイルは見に行ってるんだけど、パスフレーズの入力で/dev/ttyがねぇぞってことでコケる。もちろんコマンドで叩けばちゃんとcloneできる。ってなわけで、GCMとか色々物色して試したんですけどダメで、普通に(?)ssh-agentを使うことにしました。

まず、start-ssh-agentを使うのですがバッチファイルから呼び出すとcmdを起動してダンマリするので塩梅が悪いため、ファイルをコピーして、

コマンドプロンプト
> copy %GitD%\cmd\start-ssh-agent.cmd %AppsWinRoot%\summon-ssh-agent.cmd
    1個のファイルをコピーしました。

下から2行目のcmd起動部をREMっちゃいます。

summon-ssh-agent.cmd
    ~ 省略 ~

@IF NOT ERRORLEVEL 1 @(
REM    @CALL cmd %*
)

そして、パス設定のバッチファイル最後で召喚します。一応全掲。

setPath.cmd
@echo off
if Defined AppsWinRoot GoTo PostPathSettings
echo Portable Console is preparing environment variables.
set NOW_CD=%cd%
cd /D %~dp0..\..
set HOME=%cd%
cd /D %NOW_CD%
set AppsWinRoot=%HOME%\apps\win
set GitD=%AppsWinRoot%\PortableGit
set PATH=%GitD%\cmd;%GitD%;%GitD%\usr\bin;%path%
:PostPathSettings
echo Portable home has located in %HOME%
echo Portable applications have located in %AppsWinRoot%
call %~dp0summon-ssh-agent

VSCodeを黙らせることが目的ですので、VSCode起動バッチの方に使用するキーを追加します。ちょっとだけ多重起動対策してます。4行目のssh-add以降は、.sshconfigIdentityFileに書いたものをコピペしてください。ハードコードは美しくないんですが、この辺は後々構築が進んだら環境変数を使うことにします。

Code.cmd
@echo off
call %~dp0setPath.cmd
ssh-add -l
if ErrorLevel 1 ssh-add ~/.ssh/rsa_GitHub_HIU
start %~dp0VSCode\Code.exe

あとは、VSCodeをバッチ経由で起動しようとすると、ssh-agentがいない場合は召喚し、パスフレーズが入力されていなければそれを承認してからVSCodeが起動します。

バッチファイル動作中
Portable Console is preparing environment variables.
Portable home has located in D:\jtHiuPortable
Portable applications have located in D:\jtHiuPortable\apps\win
Removing old ssh-agent sockets
Starting ssh-agent:  done

The agent has no identities.
Enter passphrase for /d/jtHiuPortable/.ssh/rsa_GitHub_HIU:
(パスフレーズを入力してEnterキー)

ssh-agentを停止する

通常の使用であればVSCodeを開き直してもパスフレーズを再入力する必要がないので便利ですが、共有マシンなどでログインしっぱなしなのは問題がある場合も多いですし、何よりssh-agentの召喚中は「ハードウェアを安全に取り外してデバイスを取り出す」ができないので、召還するスクリプトrecall-ssh-agent.cmdapps\winに用意して、ここに飛ぶトリックショートカットRecallAgent_Win.lnkもポータブル環境フォルダに作成、必要に応じてダブルクリックして自動認証を終了させられるようにします。

recall-ssh-agent.cmd
@SETLOCAL EnableDelayedExpansion
@FOR /f "tokens=1-2" %%a IN ('tasklist /fi "imagename eq ssh-agent.exe"') DO @(
    @ECHO %%b | @FINDSTR /r /c:"[0-9][0-9]*" > NUL
    @IF "!ERRORLEVEL!" == "0" @(
        @SET SSH_AGENT_PID=%%b
        %~dp0PortableGit\usr\bin\ssh-agent -k
    )
)

要点解説:基本的にはstart-ssh-agent.cmdからPID取得部を持ってきています。

  • 1行目 … 遅延展開の使用を宣言します。
  • 2-3行目 … tasklistコマンドをforから用いて、起動中のssh-agentを検索し、PIDの部分を取得します。
  • 4-6行目 … きちんと取得できたら、ssh-agentが参照する環境変数に代入し、さよならします。

オプション:VSCodeの英語モード起動をなんとかする

インストール直後はしょうがない。ただ、ポータブル環境デバイスを他のマシンで利用する時(恐らくドライブレターが変更された時)、初回のみ英語モードで起動してしまいます。code.cmd --locale jaでもダメです。恐らく、起動時に拡張機能(各国語対応も拡張機能)を遅延読み込みするため、環境が変わってElectronが混乱している間に日本語拡張が読み込まれないままワークベンチが表示されてしまうからでは、と推測していますが、初回時(パスフレーズを入力する時)には自動的にVSCodeを再起動するように変更したCode.cmdを示します。気にならない方はウザいだけですので変更しなくて結構です

Code.cmd
@REM WARNING: This Windows command script is tainted with BASH commands
@echo off
call %~dp0setPath.cmd
ssh-add -l
if ErrorLevel 1 (
    setlocal EnableDelayedExpansion
    ssh-add ~/.ssh/rsa_GitHub_HIU
    echo ------------------------------------------------------------
    echo ** WARNING **
    echo Visual Studio Code will *RESTART* after boot. Please wait...
    echo ------------------------------------------------------------
    start %~dp0VSCode\Code.exe
  :loop
    sleep 1
    set COUNT=0
    for /f "skip=3 tokens=1" %%a in ('tasklist /fi "imagename eq code.exe"') do (
        set /a COUNT+=1
    )
    if "!COUNT!" LSS "6" goto :loop
    echo Visual Studio Code is restarting now. Please wait...
    for /f "tokens=3" %%a in ('%~dp0VSCode\bin\code.cmd --status ^| grep code') do (
        taskkill /PID %%a > nul 2>&1
    )
    endlocal
)
start %~dp0VSCode\Code.exe

要点解説:割愛
これが読めるようになると、大抵のバッチファイルは書けるはず。Electronがウィンドウ作るんで/minも>nulも効かないのがお騒がせになって残念。や、VSCodeのバグ取れるといいっすね。

クローンする

はいこれで本当にOK。早速git cloneしましょう。プライベートリポジトリの初期化はGitHubサイトの方で済ませておいてください。
2019-02-18-15-04-43.png
リポジトリを開いたら右側のClone or downloadボタンをクリック、そのダイアログがClone with SSHになっていることを確認、もしもClone with HTTPSとなっていたら、その横(画像ではUse HTTPSとなっている場所)にUse SSHリンクがあるのでそれをクリックして切替、その下のアドレスがかかれた右側にある、クリップボードに左矢印ボタンを押してアドレスをコピーします。
2019-02-18-15-02-49.png
Ctrl+Shift+Pでコマンドパレットを開き、git cloneぐらいに入力するとGit: クローンが出るのでそれを選択、
2019-02-18-15-09-20.png
リポジトリのURLを聞かれるので、入力欄をクリックしてCtrl+Vで貼り付け、
2019-02-18-15-12-54.png
Enterキーを押すとダイアログが出るので、ポータブル環境のfilesフォルダを選択してリポジトリの場所を選択ボタンを押します。するとfilesの下にリポジトリと同名のフォルダを作成して持ってきます。git initもいらないです。

下の奴が出てもこれはエラーじゃないんでビビらなくてOKです。
2019-02-18-15-15-39.png

ほら、ようやくこのダイアログに巡り合えました。
2019-02-18-16-32-19.png

手順通りにやると、最終的にはこの様な配置になります。もちろんfiles以下はクローンしたリポジトリによって様々です。

[jtHiuPortable]
├───[.ssh]
│       ├───config
│       ├───known_hosts
│       ├───rsa_GitHub_HIU
│       └───rsa_GitHub_HIU.pub
├───[apps]
│   └───[win]
│       ├───[VSCode]
│       ├───[PortableGit]
│       ├───Code.cmd
│       ├───recall-ssh-agent.cmd
│       ├───setPath.cmd
│       └───summon-ssh-agent.cmd
├───[files]
│   └───[sandbox]
│       ├───[.git]
│       ├───.gitignore
│       ├───LICENSE
│       └───README.md
├───.bash_history
├───.gitconfig
├───VSCode_Win.lnk
└───RecallAgent_Win.lnk

以上です。では、Happy Coding!


  1. .cmdファイルは「Windowsコマンドスクリプト」、.bat上位互換のいわゆるバッチファイルです。.batだと遅延展開など現代風のバッチが書けず、.ps1だと実行に管理者権限が必要な場合が多いので、ここでは*.cmdを使用します。 

  2. あ、もちろん、公開鍵だけあっても仕方がないとは言え気持ち悪いんで、このキーペアは速攻破棄しました。 

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

gitとGitHubを連携しクローン、プッシュ

はじめてGitHubを使う前に

知っておきたい用語を簡単に説明すると、

ローカル

作業しているパソコン

ローカルレポジトリ

作業しているパソコンの中にあるフォルダ

リモートレポジトリ

作業しているパソコンの外にあるサーバー上のフォルダ

git clone

git cloneとはGitHubで作ったリポジトリを作業中のパソコンにコピーするためのコマンド。

cmd
cd Desktop¥workspace¥workspace-test

まずクローンしたフォルダを置く、ローカル上のフォルダへ移動する。例えばデスクトップ上のworkspaceフォルダの中のworkspace-testというフォルダに移動するには上のように入力。(¥は半角です)

フォルダに移動したらgit cloneを実行。

cmd
git clone http://github.com/<GitHubのアカウント名>/<クローンするレポジトリ名>

cloning into <クローンするレポジトリ名>... とクローンが始まります。

先ほど移動したローカルのフォルダに、新しくクローンしてきたフォルダが作成されていたら完了です。

gitとGitHubを連携する

クローンが終わったら、パソコン上のgitを操作するためにgitを設定します。

cmd
git config user.name "GitHubのユーザー名"

git config user.email "GitHubに登録しているメールアドレス"

git push

git pushとは、作業しているパソコンに入っているフォルダの内容を、サーバー上のフォルダに反映させるためのコマンドです。

まず、git pushするファイルへ移動します。

cmd
cd Desktop¥workspace¥workspace-test¥<フォルダ名>

gitにアップするために次のコマンドを入力。

cmd
git add --all

git commit -m "<コメント>"

git push

以上でプッシュ完了です。

プッシュできないとき

複数人でパソコンを使っていたり、gitとGitHubが上手く連携していないとプッシュできないことがあるので、その場合はアカウントの連携をしなおします。

cmd
git remote set-url origin http://<GitHubのアカウント名>:<GitHubのパスワード>@github.com/<GitHubのアカウント名>/<レポジトリ名>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

チーム開発に混ぜてもらいたい人のための【Git入門】その1

branching-illustration@2x.png

はじめに

技術研修の基礎編を終えて、やっとサービスの一部に携われるようになりました。そこで、「今まで独学でプログラムの勉強をしてきたけど、まだチーム開発をしたことがない…」という方々に向けて、チーム開発をする上では欠かせない【Gitとは何ぞや】ということを、私なりにまとめさせて頂きます。

公式サイトはこちら

Gitとは

Git(ギット)は、プログラムのソースコードなどの変更履歴を記録・追跡するための分散型バージョン管理システムである。

Wikipediaより

チームで開発をする際に、どこの誰がどのような意図を持ってコードを変更したのかということがすごく大切です。【Git】を使うことで簡単にそれらの記録が行えます。

Gitの用語

リポジトリ

Gitは時系列でファイルの記録を整理できます。その管理するデータベースのことをリポジトリと言います。写真のアルバムみたいなものですかね!
database-tuning.png
画像:Section-9より

コミットとコミットメッセージ

リポジトリにファイルの変更内容を記録すること、その結果作られた記録のことをコミットといいます!アルバム(リポジトリ)の中にある写真みたいなものですね!

また、インスタなどで使われるハッシュタグのようにコミットメッセージをつけることで、どのような修正を行ったか詳細に記録に残すことができます。
Multiple-photographs-of-vacation-scenes-456859205_1255x837.jpeg
画像:Instagram(インスタグラム)にパソコンから写真を投稿する方法より

ワークツリー

Gitによってコードやファイルの変更を監視されているフォルダのこと。

ワーキングディレクトリー、ワーキングコピー、作業コピーとも呼びます。

ステージング

コミットにはコミットメッセージにそぐわない無関係の変更を含むべきではありません。しかし作業によってはワーキングツリーに大量の変更が積まれる場合があります。その時にコミットに含めたい変更を選別することをいいます。

たくさん写真を撮ったけど、どれをインスタに投稿しようかな〜ってのと同じ感じですね!

ブランチとマージ

ブランチとは履歴の流れを分岐して記録していくためのものです。分離したブランチは他のブランチの影響を受けないため、同じリポジトリの中で複数の変更を同時に進めていくことができます!
capture_stepup1_1_1.png
画像:猿でもわかるGit入門より

逆にマージとは枝分かれした変更履歴を一つにまとめることをいいます!
Merger-II_mvvsdu.png
画像:MARTECHTODAYより

コンフリクト

  • 同じ箇所を
  • 別々のブランチで
  • 別々の変更をかけてしまったのに
  • マージする

と起こってしまう「衝突」現象です。どっちの変更を受け入れればいいの?ってことですね!
こうなるとブランチのマージは一旦保留になり、ユーザが手動でコンフリクトを解消する必要があります。

次回予告

【Gitとは何ぞや】ということを簡単にですがご説明させて頂きました。次回は具体的なGitコマンドをまとめさせて頂きたいと思います。

*説明に不備やおかしな点がございましたらご指摘いただけると幸いです。

リファレンス

本当の初心者向け!Git入門のための概念から基本用語まで
git add ってなんのためにやるの? Gitの「ステージング」をイラストで解説します!
サルでもわかるGit入門〜バージョン管理を使いこなそう〜
コンフリクトって!?Gitバージョン管理でマージしたときに発生した衝突を解決する

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む