20201119のGitに関する記事は14件です。

GitでSimulinkモデルの競合を解決してマージする

はじめに

Gitはとても便利で強力なバージョン管理ツールです。
覚える用語(コマンド)や概念が多くて最初のハードル高さは否めませんが、いったんあの便利なシステムを使って複数人で同じドキュメント(ソースコード)の管理をすれば、もはやGitなしで開発してた頃が想像つかないほどには中毒性のあるシステムだと思っています。

話は変わりまして、Simulinkモデルはグラフィカルにモデリングできる1D-Simシミュレーションモデルとしての性質もありますが、産業用途では専ら“コントローラモデル”、つまりマイコンプログラムをグラフィカルに描くためのツールとして利用されています1。 そうつまり Simulinkモデル = プログラムソースコード なのです。

こうなってくると、これは是が非でも Simulinkモデルをバージョン管理したい。 そして、あの強力な差分比較とマージ機能を使いたいと思ってしまうのは人間の性というもの。

しかし、Gitはプログラムソースコードなどのテキストファイル(アスキーデータ)には、とても強力な差分比較とマージ機能が使えるのですが、Simulinkモデルファイル(.slx)のような、 “実態はテキストファイルなんだけど、 構造に意味がある系 のアスキーデータ”2 に対してGitでマージをかけると、構造が崩れて 最悪モデルファイルが壊れてしまいます。

この記事では、GitでSimulinkモデルのバージョン管理したいという人に向けて、「自動で競合の解決をしてマージする」手順について説明します。

リポジトリの事前設定

まずは事前準備として、リポジトリ直下の .gitattributes に以下の設定を施します。

*.mlx -crlf -diff -merge
*.mat -crlf -diff -merge
*.fig -crlf -diff -merge
*.mdl -crlf -diff -merge
*.slx -crlf -diff -merge
*.mlapp -crlf -diff -merge
*.p -crlf -diff -merge
*.mdlp -crlf -diff -merge
*.slxp -crlf -diff -merge
*.sldd -crlf -diff -merge
*.slxc -crlf -diff -merge
*.mlproj -crlf -diff -merge
*.mldatx -crlf -diff -merge
*.slreqx -crlf -diff -merge
*.sfx -crlf -diff -merge
*.sltx -crlf -diff -merge

これは、Gitに「Simulinkモデルファイルに対して diff (差分機能)とmerge(マージ機能)を使うんじゃねえ」と明示しています。
そうです、つまり Gitの差分比較とマージ機能は使いません。3

Simulinkモデルファイルをブランチ別に更新してみる

事前設定が終わったので、ここからは実際にSimulinkモデルファイルを競合させてマージしてみたいと思います。
まずは競合のシチュエーションを作るために、以下に示すようにそれぞれのブランチ(master, develop)でSimulinkモデル(ex_git_merge.slx)に変更を施しcommitします。

コミットグラフはこんな感じです。

コミットグラフ

それぞれのコミット(リビジョン)のモデルはこんな感じです。

ベース
masterブランチ変更
developブランチ変更

masterブランチではGainブロックの設定値を変更し、developブランチではブロックを組み替えてみました。
ブランチごとにそれぞれ違うトコロを変更したので、それぞれの変更をうまいこと自動で取り込んでマージしてくれることを期待していますが、果たしてできるのか・・・?

マージの実行 -> 競合の発生

それでは実際にマージさせてみます。
masterブランチにdevelopブランチを取り込みます。

$ git merge develop

すると、Gitから競合の発生を知らせるエラーが返ってきます。

mergeして競合エラー

Gitのマージ機能は .gitattrubutes で無効化しているので、両ブランチに変更があったらGitは 有無も言わず 「競合してるよ!」と知らせておしまいです。

MATLABの3wayマージツールを起動

ではこの状態で、MATLABでこのリポジトリを見てみましょう。
Gitがシステムにインストールされていれば、MATLABの「現在のフォルダー」ペインにもGitのステータスが表示されます。 Simulinkモデルファイルが競合マークになっていることが確認できます。
右クリックをして「ソース管理 > 競合を表示」の順にクリックします。すると、3wayマージツールが起動します。

競合を表示

3wayマージツールで競合を解決する

ここでタネあかしをすると、Simulinkモデルの競合解決はGitのマージ機能ではなく、Simulinkに搭載されている 3wayマージツール を用いて行います。(マージコミット命令自体はGitで操作する必要があります。)

3wayマージツール

3wayマージツールもGitのマージ機能に負けず劣らず優秀なツールでして、モデル内で変更箇所がかぶっていない場合(真に競合がない場合)、つまり今回のようなシチュエーションの場合は、両方の変更を取り込んで 自動でマージされた結果を表示します。 もちろんどちらの変更を採用するか手動で選択することも可能です。
競合箇所がすべて解決されていることを確認して、「確定して閉じる」を押下します。

確定して閉じる

コミットする(リベンジ)

Gitに戻り、ステータスを確認します。

$ git status

競合解決済み

競合が解決していることが確認できたので、再びコミットを行います。

$ git commit

無事に競合が解決され、以下のようにマージコミットが作られました。

merge完了

最後にSimulinkモデルを開いてみましょう。

merge後のモデル

ちゃんと masterブランチの変更(Gain変更)と、developブランチの変更(ブロックの組み替え)がうまく統合されていますね。 めでたしめでたし。

おわりに

今回はGitシステムの操作とSimulink上の操作を明確に区別するために、Git側の操作は別クライアント(Git Bash)で行いましたが、MATLABからもGitの操作は可能ですので4、よりシームレスにマージ作業ができることと思います。
また、今回はSimulinkの3wayマージツールの紹介だけでしたが、この他にもモデルの単純なリビジョン同士の比較なんかもできますので、もうこれで 「GitでSimulinkモデルのマージしたり比較したりするとぶっ壊れるんじゃ・・・((;゚Д゚))ガクガク」 と、漠然とした不安を抱える日々を送らなくてすみますね!(ワタシがずっとそう思ってた)


  1. 拙著「電子工作にモデルベース開発(Model Based Development: MBD)を適用してみた【コントローラモデル編】」を参照下さい(https://qiita.com/mana_544/items/3fe4d150441b12d89ebf

  2. Microsoft WordやExcelファイルなんかも、実態はテキスト(XML)だけど構造に意味がある系のファイルですね。 

  3. この設定も含めて、MATLAB(Simulink)でGitを使う際の細かい設定は公式HPに書いてありますのでご参照下さい。Git ソース管理の設定 - MATLAB & Simulink - MathWorks 日本 

  4. MATLABでGitの操作についてはコチラの方が詳しく解説されていますのでご参照下さい。「MATLABでGitを操作しよう (第1回 : プロジェクト作成とGUIの説明)」(https://qiita.com/stozaki/items/e4fa14c36f6c134e53e7

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

GitHub 接続時の ~/.ssh/config の書き方

はじめに

本記事ではタイトルの内容に加えて ~/.ssh/config に対する基本的な理解を深めるため、各種設定項目に関する説明も付随して行います。GitHub を例に挙げてはいるものの、Bitbucket や GitLab、Git サーバへ接続する際にも利用可能な ~/.ssh/config の設定について記載しております。

~/.ssh/config の書き方

SSH キーが未登録の場合は 公式サイトの手順 に従って鍵の生成・登録までを事前に行っておきます。

まず GitHub へ接続する ~/.ssh/config の設定を見ていきます。GitHub で認証に使用する SSH キーは登録済みで秘密鍵は ~/.ssh/github へ配置している想定です。

~/.ssh/config
Host github.com
    IdentityFile ~/.ssh/github
    User git

~/.ssh/config の各種設定項目は下記になります。

項目 説明
Host ホスト名を指定する
IdentityFile 接続時に使用する秘密鍵を指定する
User 接続時のユーザ名を指定する

設定を行うことで github.com に SSH 接続する際、ユーザ名に git が指定され、~/.ssh/github に存在する秘密鍵を用いて SSH 接続を試みるようになります。

早速 github.com 接続時に正しく認証が通っているか確認するため、適当なプライベートリポジトリを git clone してみます。

git clone の実行結果 (成功)
プライベートリポジトリを git clone した実行結果 (成功)

無事に git clone できることが確認できたら成功です。

接続先に応じて秘密鍵を使い分けたい

GitHub で常に同一の秘密鍵を用いて認証を行う際は問題ないのですが、例えば GitHub アカウントをプライベート用と仕事用で使い分けていて、リポジトリ先に応じて秘密鍵を使い分けたいというケースはあると思います。

その場合は ~/.ssh/config の設定と git のリモートリポジトリへの接続情報を変更することで対応可能です。

例えばプライベート用の GitHub アカウント A と仕事用の GitHub アカウント B が存在するとします。その際 github-A がホストの時は A の秘密鍵を、github-B がホストの時は B の秘密鍵を利用するための設定は下記になります。

~/.ssh/config
# プライベート用の GitHub アカウントで利用する接続設定
Host github-A
    HostName github.com
    IdentityFile ~/.ssh/github-A
    User git

# 仕事用の GitHub アカウントで利用する接続設定
Host github-B
    HostName github.com
    IdentityFile ~/.ssh/github-B
    User git

新たに HostName という項目を設定しました。HostName には接続先を指定します。HostName は何も指定しない場合 Host と同じ値が設定されます。

今回は同一接続先に対してアカウントを切り替えたいので、Host にはアカウント識別可能な値 (ex: github-A, github-B, etc.) を、HostName に接続先である github.com を明示的に指定してアカウント毎に設定をわけました。

次に git のリモートリポジトリへの接続情報を変更します。


~/.ssh/configUser を指定している場合は該当 Host へ接続時に自動的にユーザが設定されるため、接続 URL からユーザ名である git は取り除いても問題ありません。

# 現在のリモートリポジトリ URL
git remote -v

origin  git@github.com:nikaera/private-repository.git (fetch)
origin  git@github.com:nikaera/private-repository.git (push)

# リモートリポジトリ URL を
# git@github.com:nikaera/private-repository.git から
# github-A:nikaera/private-repository.git に変更する
# (ユーザ名の git は変更先から取り除いている)
git remote set-url origin github-A:nikaera/private-repository.git

# 新たに設定したリモートリポジトリ URL
git remote -v

origin  github-A:nikaera/private-repository.git (fetch)
origin  github-A:nikaera/private-repository.git (push)

この状態で先ほど git clone してきたプライベートリポジトリ内で git ls-remote origin コマンドを実行してみて正常に結果が取得できれば正しく設定できています。

`A` の接続設定で `git ls-remote origin` の実行に成功する
A の接続設定で git ls-remote origin の実行に成功する

次に B のアカウント情報で接続を試みます。

# 現在のリモートリポジトリ URL
git remote -v

origin  github-A:nikaera/private-repository.git (fetch)
origin  github-A:nikaera/private-repository.git (push)

# リモートリポジトリ URL を github-A:nikaera/private-repository.git から
# github-B:nikaera/private-repository.git に変更する
git remote set-url origin github-B:nikaera/private-repository.git

# 新たに設定したリモートリポジトリ URL
git remote -v

origin  github-B:nikaera/private-repository.git (fetch)
origin  github-B:nikaera/private-repository.git (push)

B には先ほどのプライベートリポジトリの読み取り権限が無い状態で、git ls-remote origin コマンドを実行してみると失敗するはずです。

`B` の接続設定で `git ls-remote origin` の実行に失敗する
B の接続設定で git ls-remote origin の実行に失敗する

これで今後は git のリモートリポジトリ URL を一度書き換えておくだけで、それぞれ適切な秘密鍵で GitHub 認証する設定ができました。

単に Git サーバに SSH 接続する際の設定情報としては、上記項目を抑えておけば問題無いです。しかし、他にも設定したほうが良い項目や、場合によっては設定が必要な項目も存在します。

基本的に設定しておいた方が良い項目

他に設定しておいたほうが良い項目には下記があります。

~/.ssh/config
Host github.com
    IdentityFile ~/.ssh/github
    User git
    IdentitiesOnly yes # IdentityFile で指定した秘密鍵でのみ認証を試みる
    Compression yes # Git でのファイル転送時に圧縮する
項目 説明
IdentitiesOnly IdentityFile で指定した鍵ファイルでのみ認証を行うかどうか指定する boolean (yes or no)
Compression 圧縮転送を行うかどうか指定する boolean (yes or no)

IdentityFile で指定したファイル以外で認証が通ってしまう状況だと、意図したアカウントで適切に認証が通せていない可能性が出てきてしまいます。

そのため、特別な理由がなければ IdentitiesOnly には yes を設定しておいたほうが良いです。

IdentitiesOnlyno に設定しておくと ssh-add で登録したキーの中からも認証を試みるようになります。

また、Compression についても yes に設定しておくことをオススメします。プログラミングを行っているプロジェクトでは、テキストファイルの数が大半を占めるはずなので、圧縮転送を有効にしておいたほうがファイル転送の速度向上を見込めるからです。

ただし Compression は大容量の単一のファイルがアップされているなどして、圧縮効率の悪いファイルを含んでいるプロジェクトの場合は逆に転送速度が低下する恐れもあるので要注意です。

接続先によっては設定が必要な項目

接続先に応じて設定する必要がありそうな項目には下記があります。

~/.ssh/config
Host github.com
    IdentityFile ~/.ssh/github
    User git
    Port 12345 # 接続先のポートが 22 以外の場合指定する
項目 説明
Port SSH 接続時のポート番号を設定する number (ex: 22, 22222, etc.)

例えば自前で用意した Git リポジトリに対して接続する場合、SSH のポートがセキュリティ上の理由等でウェルノウンポートの 22 ではない場合がありえます。その場合は Port を明示的に指定することで接続時のポート番号を適切な値に設定しておく必要が出てくるでしょう。

おわりに

今回は GitHub へ SSH 接続する際の例を元に ~/.ssh/config の設定方法について書きました。~/.ssh/configHost の設定は行っているものの、それに応じて git のリモートリポジトリ URL を変更すべき場合もあることを明示している記事が少なかったので書きました。

また、本記事では Git 接続時の ~/.ssh/config の設定にフォーカスを当てましたが、~/.ssh/config についてはサーバに SSH 接続して作業する際に設定しておくと良い項目等もあります。

~/.ssh/config の各種設定項目について理解していると頻繁に実行するコマンドのコスト削減ができて便利です。特に @oohira さんの こちらの記事 はとても参考になりました。

参考リンク

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

rebaseをちゃんと理解して使えるようになろう!

簡単なrebaseの説明

簡単なレベルあれば、サル先生のGit入門で十分なのでこちらを参照ください。
サル先生のGit入門: rebase

mergeとの違い

rebase、mergeはどちらもブランチを統合するコマンドになります。
実際の作業ベースではどんな違いがあるのでしょうか?

コミットが改変される?

merge

  • 単純な統合なので、基本はマージコミット1つ追加される
aブランチ
        * e750862 Dコミット
        * 2f6c625 Cコミット
        * cf890e0 Bコミット
        * 8721950 Aコミット
に
bブランチ
        * f23vd43 Eコミット
        * 2f6c625 Cコミット
        * cf890e0 Bコミット
        * 8721950 Aコミット
をマージすると

⬇️

aブランチ(fast-forward場合)
        * f23vd43 Eコミット
        * e750862 Dコミット
        * 2f6c625 Cコミット
        * cf890e0 Bコミット
        * 8721950 Aコミット
または
aブランチ(non-fast-forward場合)
        * fas34vs Fコミット(マージコミット)
        |\ 
        | * f23vd43 Eコミット
        |/ 
        * e750862 Dコミット
        * 2f6c625 Cコミット
        * cf890e0 Bコミット
        * 8721950 Aコミット

rebase

  • rebaseはコミットが改変されることがある。
bブランチ
        * f23vd43 Eコミット
        * 2f6c625 Cコミット
        * cf890e0 Bコミット
        * 8721950 Aコミット
を
aブランチ
        * e750862 Dコミット
        * 2f6c625 Cコミット
        * cf890e0 Bコミット
        * 8721950 Aコミット
でリベースすると

⬇️

bブランチ
        * 34jfil3 Eコミット
        * e750862 Dコミット
        * 2f6c625 Cコミット
        * cf890e0 Bコミット
        * 8721950 Aコミット

rebaseの場合はEコミットのハッシュ値が書き換わってしまいました。
コミットメッセージが一緒なだけで、別物のコミットと認識されてしまいます。

rebaseしたら何が変わる?

先ほどはハッシュ値が変わることを説明しました。
変わるのは他にもあります。

CommitDateです。
コミットにはAuthorDateCommitDateが管理されています。

git logで出力される方はAuthorDateになります。

rebaseのリスク

もとに戻せないかも

ブランチ統合しようとしたら、なんかよくわからない状況になってしまった。(初心者あるある)
mergeはコミットが追加されるだけなので、もし失敗した場合はresetを使って元に戻すことができます。
しかし、rebaseはコミットが改変されてしまうので、バックアップを取っておかないと、取り返しのつかないことになってしまうかも知れません...

これが、理由でrebaseを使わないGit初心者がちらほら...

rebaseした後は強制プッシュ必須

一度プッシュしたブランチでrebaseを行うとコミットが改変されるため、再度プッシュできなくなります。
rebase前のコミットとrebase後のコミットは異なるものと判断されるためnon-fast-forwardな状態になってしまいます。

git push -fは危険なのでgit push --force-with-leaseを使って再度プッシュする癖をつけましょう。

他の開発者のコミットも改変させてしまうかも

git flowでいうdevelopmasterブランチ(複数人のコミットが入ったブランチ)で同様なことを行うと、他のメンバーのコミットをいつの間にか変えてしまうかも知れません。

なぜrebaseするの?

複数人で開発する際はこのような事象が発生すると思います。
例: rebaseしない場合
1. Aさんは13時に実装を終えてコミット、プルリクエストを出した。
2. Bさんは14時に実装を終えてコミット、プルリクエストを出した。
3. Bさんは指摘箇所なしで、当日の夕方にマージされた。
4. Aさんは指摘された箇所が多すぎて、マージできたのは翌日の朝でした。

rebaseをしないと以下のようなログの順序になります。

* Aさんのマージコミット 9:00
* Aさんの指摘取り込み用コミット(その3) 21:00
* Bさんのマージコミット 18:00
* Aさんの指摘取り込み用コミット(その2) 17:00
* Aさんの指摘取り込み用コミット(その1) 16:00
* Bさんの実装コミット 15:00
* Aさんの実装コミット 14:00

もうすでに複雑ですよね...
あとで見返した時にどこを確認すれば良いかわからなくなってしまいます。
また、指摘取り込み用コミットがいくつも入っています。
このコミットのせいでAさんのどんな実装をしたか一目ではわかりません。

例: rebaseを使った場合
1. Aさんは13時に実装を終えてコミット、プルリクエストを出した。
2. Bさんは14時に実装を終えてコミット、プルリクエストを出した。
3. Bさんは指摘箇所なしで、当日の夕方にマージされた。
4. Aさんは指摘された箇所が多すぎて、LGTMされたのは翌日の朝でした。
5. Aさんはrebaseしてコミットを1つにしてから、マージしてもらった。

rebaseを使うと以下のようなログの順序になります。

* Aさんのマージコミット 9:00
* Aさんの実装コミット 14:00
* Bさんのマージコミット 18:00
* Bさんの実装コミット 15:00

綺麗になりました。
これなら、Aさんがどんな実装をしたかはAさんの実装コミット 14:00を確認すれば良いと一目でわかります。

rebaseにはこのようなメリットがあります。

安全にrebaseを使うには

プロテクトブランチを活用しよう

GitHubやGitLabにはプロテクトブランチという機能があります。
developmasterブランチではプッシュを許容しないように設定すれば、rebaseして壊れたブランチを間違ってプッシュしたとしてもリジェクトされるので保護されます。

自分のコミットだけが枝分かれしているときだけrebaseしよう

基本、featureブランチを作成し開発してコミットしますよね?
そうであれば、枝分かれしたコミットは自分のものだけなハズです。

こういう時だけrebaseを使うように心がけましょう。
それでも不安な場合はバックアップ用のブランチを作成してチャレンジしましょう。

sandboxなリポジトリをつかってrebaseを試して見よう

重要なリポジトリで初めてrebaseするのはやはりリスクがあります。
汚してもいいリポジトリを作成してrebaseを試してみましょう。

Git職人に付いてもらってrebaseしてみよう

隣にGit職人がいれば安心です。

まとめ

今回rebaseのメリットについてあまり触れませんでしたが、もちろんログが綺麗になるという大きなメリットがあります。

個人的には

  • リモートリポジトリではmerge(プルリク)
  • ローカルリポジトリではrebase(最新情報を取得)

なイメージを持っています。

ログを綺麗に保つことは後々ログを見返すと気に役立ちますので、
今後意識してGit使ってもらえれば....と思います。

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

Githubについて

なぜ使うか

 なぜわざわざわGithubなんてものを使うかというと,自分は以下のモチベ―ションで使っている.

  • ファイルが突然消えてしまうのを防ぐため.ローカルのファイルはいつでも消え得る.PCに水をこぼして壊してしまったり,まちがえて削除してしまったりなど.自分も個人開発していたときに悲劇に見舞われてから,Githubを使うようになった.何十時間,何百時間もかけてかいたコードが一度でも消えてしまった経験があれば,Githubからは離れられなくなる.
  • 他の人と一緒に開発できる.sandbox内だけではあまり恩恵を感じないかもしれないが,それでも他の人の進捗状況を把握したりできる.コードに誤りがあれば指摘できる.もちろん,同時に開発できるのが強み.
  • 何かと就活で求められる.応募条件にGithubが使えることが必須という場合が多々.というか,Github自体は正直まったく難しくないので,「え?できないの?ヤバくね?」という感覚でもある.
  • 他人に自分の成果を見せびらかせる.個人開発したプロダクトのコードを披露する場でもあるし,就活でもよく見せる.大学院入試でも使った.もちろん,sandboxだって,上司に自分がどれだけ仕事をしているのか具体的にアピールする場だと思う.1週間一度も更新されてなかったら,「この人仕事してなくね?」って思われても仕方がない.だってコード書いていないのと同じなのだもの.

 割と下心多めだが,個人的にはこんな感じ.

Github 基本編

 さて,Githubを使いたくなったら,次は実践である.とにかく使おう.Github上にファイルをアップロードするだけなら,まったく難しくない.たった5ステップ.以下がコードだ.

# gitを初期化する -> このフォルダでgitを利用しますよ,という宣言.
$ git init

# レポジトリを登録する -> レポジトリとはGithub上のフォルダ.レポジトリを作成したら,レポジトリのurlを登録しよう.アップロード先を登録する感覚.
$ git remote add origin https://github.com/...

# コミットするファイルを指定.「.」とは全てのファイルという意味..gitignoreやdockerなど様々な場面で使うから覚えておこう.ここはあまり気にせずgit add .しておけばいいと思っている.
$ git add .

# コミット.ローカルの中で保存するイメージ.アップロードする準備でもある.コミットメッセージは何でもいいが,「update ファイル名」とか変更点をメモする感じ.コミットメッセージの意義は後述.
$ git commit -m "コミットメッセージ"

# Githubにファイルをアップロードする.originとはレポジトリのurl(git remote add で指定したでしょ).masterとはブランチの名前(後述).
$ git push origin master

 以上これだけ.本当に簡単.だって,たったの5ステップ.

 ここで注意点だが, 直接アップロードは厳禁.これらはすべてコマンドラインで完結させる.でないと手間がかかって仕方がない.(ちなみにコマンドラインはVSCodeの下にくっついているターミナルのこと.)

Github 発展編

 以上で述べた内容は,自分が個人で使ってたときの理解.これでとくに困ったことはなかったが,ミルプラトーで一応チームでやる中で,発展的な内容も学んだので,ここに記しておく.sandbox内で作業するだけであれば,とくに使う場面もないとは思う.が,やっぱり理解しておくと役立つ.

# 既存のレポジトリを引っ張ってくる.チーム外であればgit clone, チーム内であればgit pullという理解.git pullは変更点のみ引っ張ってくるため軽い.
$ git clone ... / git pull ...

# ログを確認する.元に戻したくなったときなどに使う.
$ git log
$ q (ログから抜ける)

# ブランチを作成する.複数人のときに使う.ブランチ切って開発進めたり,プルリクしたり.
$ git branch branch_name

# ブランチを切り替える
$ git checkout branch_name

# プルリクエスト -> pushして,Github上でCompare & pull request. 大元のコードと統合するとき.ちなみにプルリクエストはGithubの機能.
$ git push origin branch_name

# コミットを取り消す. revert は基本的に直前のコミットの取り消しのみに使う.
$ git revert commit_id
$ git revert HEAD
$ git revert --no-edit coomit_id

# git reset -> HEADの位置を大きく移動できるが,以前のコミットの復元に手間

# 直前のコミットを取り消したい
$ git reset --hard HEAD^

# n個前のコミットまで戻したい
$ git reset --hard HEAD~n

# 誤ってresetをしてしまった場合
$ git reset --hard ORIG_HEAD

Github 趣味編

 コミットはできるだけ細かく.コードを元に戻したくなったとき,他の人がコードをチェックするときに役立つ.余裕があるときは自分は以下の記法を採用している.

1行目: コミットの内容を表す絵文字 + 変更内容を簡潔に英語の命令形で記述
2行目: 空行
3行目以降: なぜ変更したのか詳細な説明を日本語で記述

$ git commit -m ":bug: fixed bug"

こうすると, ? fixed bugみたいに表示されて分かりやすい.そして楽しい.導入は .commit_templateを追加するだけ.vad-sandbox/.commit_template at master · milplateaux/vad-sandbox

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

【GitHub】upstream masterを自分のブランチに取り込む方法

●<GitHub upstream masterを取り込む方法>

http://kik.xii.jp/archives/179
remote:upstream
remote: master、origin
local: master、origin

①upstreamのmaster → localのmaster
②localのmaster → remoteのoriginにpush
③remoteのmaster → localのブランチ

git checkout master
git pull upstream master ①
git push origin master ②
git checkout ブランチ名
git pull origin master ③
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[初心者向け]GitとGitHubの使い方を徹底解説

はじめに

今回の記事は、GitとGitHubについてまとめていきます。

GitHubについてほとんど知らない人を対象に作成しているので、知っている人からすればかなりくどい説明になると思います。

お付き合い頂ければ幸いです。

Gitの歴史と環境構築

最初に、Gitの歴史と環境構築についてまとめていきます。

そもそもGitHubとは

GitHubの説明の前に、Gitの説明からはいります。Gitとは、簡単に説明するとファイルのバージョン管理システムのことです。
ファイルの変更履歴を各々のパソコン(ローカル環境)に保存することで、その変更履歴をたどることでファイルの状態を戻すことができます。

GitHubとは、そのGitをオンライン上に設置することで、集団でのファイルの編集を可能にするサービスのことです。

GitHubはGitHub社という会社により運営されていましたが、近年マイクロソフト社によって買収されました。

Gitの歴史

Gitを開発したのは、かの有名な世界最大規模のオープンソースソフトウェアであるLinuxの創造主であるリーナス・トーバルズです。
Linuxの開発は複数人のエンジニアにより行われるのですが、Linuxに対するどの変更を許可し、またどの変更を許可しないかなどを管理するバージョン管理システムが使用されていました。

元々Linuxの開発にはBitKeeperというバージョン管理システムが使われていたのですが、ライセンスなどの問題で開発元のBitMover社とLinux開発コミュニティとの間の協力関係が崩壊してしまい、急遽別のバージョン管理システムが必要になりました。

それにより生まれたのがGitです。つまり、GitはLinuxプロジェクトのために開発されたものなのです。

Linuxは1500万行にも及ぶコードから構成されるとても大規模なプロジェクトです。そのため、Linuxのためのバージョン管理システムであるGitには動作速度に非常に優れていて、また大人数で取り扱うことができるようにプロジェクトの枝分かれさせた「ブランチ」の並列開発が可能になっています。

Gitの特徴

従来のバージョン管理システムはファイルの変更差分を記録していましたが、Gitは各々のファイルのバージョンをスナップショットとして保存していることが挙げられます。違いを図で見比べてみましょう。差分を記録する場合は以下のようになります。
6.PNG

上図のように、変更差分を「レポジトリ」という場所に記録することで、バージョン管理を行うのが従来のバージョン管理システムでした。

しかし、この管理の仕方の場合、大規模なプロジェクトにおいて枝分かれして開発を行い、それを統合するときに全ての差分を計算しなければならないため、非常に時間がかかっていたのです。(枝分かれして開発するときの枝のことをブランチといい、そのブランチを統合することをmマージと呼びます)。

そこで、Gitは以下のようにバージョン管理システムを変更したのです。

8.PNG

このように、各々のファイルの状態をスナップショットとして記録することで、枝分かれした開発のブランチをマージする際に非常に高速になります。

このGitのファイル管理の仕方は非常に重要なので、しっかりと頭に入れておいてください。

とりあえずGitHubとGitを使えるようにする

とりあえず、GithubとGitの環境構築をしていきましょう。

Gitのダウンロード

自分の環境がWindowsであるため、Windowsにおける説明が主になります。「git for windows」を公式サイトからダウンロードしましょう。Macの人はこちらの記事を参考にインストールしてみてください。

ダウンロード後は、ダウンロードのショートカットにあるexeファイルからインストーラーを実行しましょう。流れにそってNextを押しまくれば、インストールは終了です。

インストールが終わった後、画面左下のWindowsのマークを押して、Gitのプログラムを探してみてください。Git BashやGit GUIなどのソフトがダウンロードできていれば成功です。

GitHubへの登録

Gitのダウンロードが終了した後は、こちらからGitHubのアカウントの取得に取りかかりましょう。右上のSign upと書かれているところから、ユーザーネームとメールアドレスとパスワードを登録して、アカウントを作成してください。無料プランでも有料プランでも、どちらでも構いません。そんなに重要な選択肢はないので、流れに合わせていけばアカウントの作成は完了です。

GitHubへの公開鍵認証(SSH接続)について

ローカルの環境のGitとサーバー上のGitHubの接続には、公開鍵認証によるSSH接続が多く使われています。今回はその設定を解説します。個人的には、この部分がはまりポイントの一つだと考えています。まずは公開鍵認証の説明をはじめます。

公開鍵認証とは、リモートのコンピューターとローカルのコンピューターを安全に接続する方法です。秘密鍵と公開鍵を用いて、接続を行います。イメージとしては、公開鍵が南京錠のようなもので、秘密鍵がその南京錠のカギのようなものです。

今回の例では、公開鍵をGitHubのアカウントに渡します。そうすると、GitHub側では公開鍵(南京錠)を用いて接続をロックし、その南京錠の鍵である秘密鍵を持つ人だけの接続を許可するようになります。以下に図解します。
9.PNG

分かりにくい図になってしまった感じがありますが、解説します。左のGitHubのサーバー上に公開鍵がある場合、その公開鍵を開ける秘密鍵をもっているのは上の笑顔の人だけであるため、笑顔の人はログインできますが、下の明らかに悪人顔の人はログインできません。このようにして、セキュリティを高めているのです。

GitHubへの公開鍵認証のやり方

こちらのサイトを参考にしたら恐らくできると思いますが、失敗しないように、注意ポイントを解説します。

まず以下コマンドでフォルダを移動してください。

cd ~/.ssh

~/.ssh はホーム直下のsshファイルの保存場所を表しています。

できるだけ、この場所で鍵の生成をして下さい。なぜなら、別の場所で秘密鍵を生成すると、「こんな安全じゃない場所の秘密鍵なんて使いたくない」というエラーが発生する場合があるからです。

Macならchmodコマンドで鍵の安全度を変更することができますが、Windowsでは鍵の場所を移動させるしかないため(他に方法があるのかもしれませんが)、少し面倒くさいです。

そして、GitHubがデフォルトで見に行く鍵の場所が「~/.ssh/id_rsa」、「~/.ssh/id_dsa」、「~/.ssh/identity」の三つであるため、別の場所で鍵を作成したり、また作成した鍵の名前を変更したりすると、GitHubに鍵の場所を教えるために「~/.ssh/config」にファイルを作成し、鍵の場所についての情報を記載する必要があります。

次は以下のコマンドを実行しましょう。

ssh-keygen -t rsa

このコマンドを実行すると最初に鍵を生成する場所を聞かれます。デフォルトでは.ssh/ 直下に「id_rsa」と「id_rsa.pub」という名前で秘密鍵と公開鍵が作成されます。「id_rsa.pub」が公開鍵で「id_rsa」が秘密鍵です。このデフォルトの名前で保存すると、「~/.ssh/config」に鍵の場所を記載せずともデフォルトで見にいってくれるので、特にこだわりがない限りはそのままでいきましょう。一回エンターを押します。

次にパスフレーズを聞かれますが、これは秘密鍵を使用する際に使われるパスワードのようなものです。設定しなくても問題はありませんが、セキュリティが心配なら適当なパスフレーズを入力しましょう。

次は、公開鍵をこちらからGitHubにUPしましょう。titleに公開鍵の名前を(そんなに重要ではない)、Keyに公開鍵の中身を貼り付けましょう。公開鍵の中身を貼り付けるときに、/.ssh/id_rsaからファイルを開こうとしても恐らく開くことができないので、以下のコマンドでクリップボードにコピーしてください。

$ pbcopy < ~/.ssh/id_rsa.pub (Mac)
$ clip < ~/.ssh/id_rsa.pub (Windows)

公開鍵をUPしたら、次のコマンドで実際に接続が上手くいっているのか確かめてみましょう。

ssh -T git@github.com

以下のメッセージが返されれば成功です。

Hi (account名)! You've successfully authenticated, but GitHub does not provide shell access.

もしも失敗してしまった場合は「~/.ssh/config」を作成し、以下の文章を貼り付けましょう。

Host github github.com
HostName github.com
IdentityFile ~/.ssh/id_rsa
User git

三行目のIdentityFile の後ろは自分の秘密鍵のPATHを入力してください。

vimエディターが入っている場合は

vim ~/.ssh/config

とするとconfigファイルを作成することができます。

Gitの初期設定

これで最後の設定です。自分のローカルのGitに、リモートのGitHubのメールアドレスと場所を教えてあげましょう。Macの方はターミナルを、Windowsの方は全てのプログラムからGit Bashを開きましょう。開いたら、以下のコマンドを入力してください。

git config --global user.name 'user_name' # user_nameにはGitHubに登録したuser nameを入力

git config --global user.email 'user@gmail.com' # user@gmail.comにはGitHubに登録したメールアドレス

上のコマンドを入力すると、homeの直下にある「.gitconfig」ファイルに変更が入力されます。このhome直下の.gitconfigファイルはGit全体の設定に関わるファイルであり、上記のコマンドを入力することでローカルのGitにネットワーク上のGutHubを登録することができます。以下のコマンドで、きちんと登録されたか確認することができます。

git config user.name
git config user.email

上のコマンドで、自分が登録したアカウント名とメールアドレスが表示されれば成功です。

ここまでで、環境構築ができました。

それでは次に、GitHubにpushするまでを見ていきましょう。

とりあえずGitHubにpushする

GitHubにpushするまでの流れをざっと見ていきましょう。自分の場合はIDE(総合開発環境)としてPycharmを用いて、pythonスクリプトをGitHubにpushしていきます。

D:\Users\lesson_gitをプロジェクトファイルとして、lesson.pyというpythonスクリプトを作成します。このpythonファイルをGitHubにpushしていきます。

GitHubにファイルをpushするまでの流れは以下のようになります。
4.PNG
リポジトリとは、情報を保管する場所だと覚えておきましょう。

まず、ファイルに変更があった場合、git addでステージングエリアという控室のような場所にファイルを追加し、その次にgit commitでローカルの情報の保管場所であるローカルリポジトリに情報を保存します。

そのあとでgit pushコマンドでネット上の情報の保管場所であるリモートリポジトリに情報を保存します。

リモートリポジトリが、GitHubに対応します。

git initコマンドで.gitファイルの作成

まずはコマンドプロンプトを開いて、lesson.pyが存在するプロジェクトファイルまで移動しましょう。

cd D:\Users\lesson_git

最初にCドライブにいる場合は、まずDドライブに移動する必要があるので以下のコマンドを打ちましょう。

D:

プロジェクトファイルまで移動した後は、次のコマンドを打ちましょう。

git init

このコマンドを打つと、プロジェクトファイル直下に.gitファイルが作成されます。中身をみていきましょう。
12.PNG

.gitファイルの中身には、このように様々なファイルがあります。Gitはプロジェクトファイルごとに.gitファイルを作成し、その.gitファイルの中に様々な情報が保存されます。ローカルリポジトリに情報を保存する場合や、ステージングエリアに情報を保存する場合も、結局はこの.gitファイルに変更が加えられることになります。3.PNG

git addコマンドでステージングエリアにファイルを追加

lesson.pyに以下のコードを打ちます。

print('Hello GitHub')

このコマンドをGitHubにpushしましょう。

次に、git addコマンドでファイルをステージングエリアに追加します。

git add lesson.py

git add ファイル名 という感じでコマンドを打ちます。すべてのファイルをステージングエリアに追加する場合は

git add .

としましょう。

git commitでローカルリポジトリにファイルを追加

ステージングエリアにファイルを追加した後は、次のコマンドでローカルリポジトリにファイルを追加しましょう。

git commit

このコマンドを打つと、デフォルトではvimエディターが立ち上がります。ここで打つメッセージは、後でファイルの変更履歴を確認するときに見ることになります。Gitは自分一人ではなく多くの人でファイルを管理するためのツールなので、ここに打つメッセージは慣習に従いましょう。

1行目:変更内容の要約
2行目 :空行
3行目以降:変更した理由

とすることが望ましいです。細かい書き方はこちらの記事に書かれているので、参考にしましょう。自分は以下のようにコメントを打ちました。

add lesson.py
(空行)
practice GitHub

vimエディタの使い方がよく分からない人は、
テキストエディタVimの使い方【超初心者向け】
知識0から始めるVim講座
などの記事を参考にしてください。
:wq でメッセージを保存するとcommitは終了です。

リモートリポジトリにpush

次はリモートリポジトリにpushしましょう。
まずはGitHubにログインして、右上の+ボタンからNew repositoryで新しいリポジトリを作成します。PublicとPrivateを選択できますが、これはどちらでも構いません。自分はPublicを選択しました。リポジトリを作成すると、上から三つ目に次のような画面がでると思います。
13.PNG

自分は今回はhangi4343というアカウントでqiita_practice.gitというリポジトリを作成しました。GitHubのコマンド通りに、コマンドラインに入力しましょう。hangi4343/qiita_practice.gitの部分は自分のアカウント名とリポジトリ名に変更して、以下のコマンドを打ってください。

git remote add origin https://github.com/hangi4343/qiita_practice.git
git push -u origin master

以上のコマンドで、リモートリポジトリにpushすることができたと思います。とりあえず、これで全体の流れは終了です。次は各々のコマンドを細かく見ていきましょう。

git add と git commitについて

git add やgit commitを実行すると、内部的にはGitオブジェクトというものが作成されます。

Gitオブジェクトには、ファイルを圧縮したblobオブジェクトと、ファイル名とファイルの中身を組み合わせたツリーファイル、「いつ、誰が、何を、何のために変更したか」が分かるコミットファイルの三つが含まれます。

このGitオブジェクトの情報は、全て.gitファイルの中に保存されています。

各々のコマンドで何が起こっているのかを図解します。
14.PNG

git add practice.pyを実行すると、practice.pyファイルの圧縮ファイルであるblobオブジェクトがローカルリポジトリに作成され、ステージにそのblobオブジェクトのファイル名(blobオブジェクトのファイル名はファイルの中身にヘッダーをつけ加えた文字列をハッシュ関数で暗号化したもの)と元々のファイル名であるpractice.pyを組み合わせたものが作成されます。

このステージの組み合わせにより、圧縮前のファイルと圧縮後のファイルの紐づけが可能となります。ここまでがgit addを実行すると内部的に起こります。

次にgit commitを実行すると、リポジトリにツリーファイルとコミットファイルが作成されます。ツリーファイルはblobオブジェクトのファイル名と元々のファイル名であるpractice.pyを組み合わせたものが保管され、コミットファイルには

  • ツリーファイルの名前
  • 作成者
  • 日付
  • コミットメッセージ

が記録されます。git addとgit commitにより、以上のことが内部的に起きています。このことはしっかりと頭に入れておきましょう。

リモートリポジトリにpushする時のコマンドについて

リモートリポジトリにpushする時に以下のコマンドを打ちました。

git remote add origin https://github.com/hangi4343/qiita_practice.git
git push -u origin master

このコマンドについて解説していきます。

git remote add origin https://github.com/hangi4343/qiita_practice.git

このコマンドは、originというショートカットに後ろのURLのリポジトリを登録する、という意味のコマンドです。これから何度もリモートリポジトリにアクセスするときにURLをいちいち打つのは面倒くさいので、originというショートカットに割り当てているだけです。

originの部分は、他の単語でも問題ないのですが、慣習的にoriginという名前を用います。というのも、git clone というコマンドを打ち込むときに、クローン元のリポジトリをデフォルトではoriginという名前に割り当てるため、その部分からきている慣習っぽいです。

次のコマンドをみていきましょう。

git push -u origin master

git push <リモート名> <ブランチ名> とすることで、<リモート名>のリポジトリに<ブランチ名>のローカルのブランチをpushすることになります。ブランチというのは、開発を枝分かれさせたときの枝のひとつのことで、ブランチを増やしていない限り、デフォルトのブランチ名はmasterとなっています。-u オプションを指定することで、次回から git pushとするだけでorigin リポジトリにmasterブランチをpushすることができます。

それでは次にブランチとマージ、プルリクエストについてみていきましょう。

ブランチ・マージ・プルリクエスト

それではこれから、ブランチはマージ、プルリクエストについてまとめていきます。

GitHubとのやりとりについて

次のコマンドで、設定しているリモートリポジトリの情報を表示することができます。

git remote # リモートのショートカット名を表示
git remote -v # リモートのURLを表示 

origin
origin https://github.com/hangi4343/qiita_practice.git (fetch)
origin https://github.com/hangi4343/qiita_practice.git (push)

次のコマンドで、GitにGitHubのリポジトリを登録することができます。

git remote add <リモート名> <リモートのURL>

前回は、originというショートカットにGitHubのリポジトリを登録しました。

ブランチについて

GitHubではブランチという概念があります。ブランチとは、開発を枝分かれさせた際の一つ一つの枝のことです。

実際に以下のコマンドで現在のブランチを確認してみましょう。

git branch

* master

ブランチを増やしていないため、今はmasterブランチというブランチしかありません。ブランチを増やすことを「ブランチを切る」と言ったりします。次のコマンドでブランチを切ってみましょう。

git branch branch_test

このコマンドを打つと、新しくbranch_testブランチを切ることができます。もう一度git branchコマンドで確認してみましょう。

git branch

branch_test
* master

branch_testという新しいブランチができていることが確認できます。*がついているのが今現在作業しているブランチになっています。

ここまでで実際にブランチを作成してみました。では、ブランチという概念についてもう少し細かく見ていきましょう。

以下の図を見てください
17.PNG

Gitはコミットによってファイルの状態が変化します。

つまり、どのコミットの状態を保持しているかで、ファイルの状態が決まるのです。

ブランチとは、どの部分のコミットの状態を保持しているかのポインタであるということができます。今、branch_testブランチを切っただけではmasterブランチとbranch_testブランチは同じコミットを指しているため、ファイルの状態は全く同じになります。

また、HEADというものも存在し、このHEADはいずれかのブランチを指し示すことで現在のブランチを決定しています。今はmasterブランチにいるので、HEADはmasterを指しています。

HEADが指すブランチを変更するには、git checkoutコマンドを使います。

git checkout branch_test

これで現在のブランチを変更することができました。確認してみましょう。

git branch

* branch_test
master

図で見ると以下のように変化したことになります。
18.PNG

この状態で変更を加えてcommitしてみましょう。lesson.pyを次のように変化させます。

lesson.py
print('Hello GitHub')
print('create new branch')

この変更をcommitしましょう。

git add lesson.py
git commit -m "add create new branch"

git commit の-mオプションで、vimエディタを開かずにコメントを追記することができます。このcommitにより、次のように変化します。

20.PNG

この状態で、git checkoutコマンドによりmasterブランチに移動しましょう。どのようになるか分かりますか?

git checkout master

lesson.pyを確認してみましょう。以下のようになっていると思います。

lesson.py
print('Hello GitHub')

print('create new branch')というコードが存在しないことが分かります。図解すると以下のようになります。
21.PNG

先ほどのコミットはbranch_testブランチにおいて行ったコミットであるため、masterブランチはコミット前の状態になっています。このようにしてブランチを切って開発を進めることで、複数人で開発をすすめることができます。

では、最後にmasterブランチにbranch_testブランチを統合して、コミット④をmasterブランチに反映させましょう。

このようにブランチを統合させることをマージといいます。以下のコマンドを打ちましょう。

git merge branch_test

このコマンドにより、masterブランチとbranch_testブランチがマージされました。図にすると次のようになります。
22.PNG

Gitにおいては、このようにブランチを切ってマージすることが開発の基本になります。また、このようなマージの仕方をとくにFast Forwardといいます。

最後に、必要なくなったbranch_testブランチを削除しましょう。

git branch -d branch_test

GitHubから情報を取得する

リモートリポジトリが他の人からのプルリクエストにより変更した場合を考えてみましょう。自分は以下のようにgit_fetch.pyファイルを作成しました。
15.PNG

このようにリモートとローカルのリポジトリの状況に差異があるときには、ローカルのリポジトリを更新する必要があります。

リモートから情報を取得するときに用いるgit fetch コマンドとgit pullコマンドをみていきましょう。

git fetchコマンドについて

今回はリモートのURLにoriginというショートカットを作成しているので、以下のコマンドでローカルに情報を保存することができます。

git fetch origin

git fetchコマンドを打つと、remotes/origin/masterというブランチにリモートの情報が保存されます。次のコマンドでブランチを確認してみてください。

git branch -a

* master
remotes/origin/master

git branchコマンドを打つと、ローカルのgitのブランチが表示され、-aコマンドを打つと、remotesも含めた全てのブランチが表示されます。
*がついているのが今いるブランチです。

git fetchコマンドによりリモートのリポジトリをローカルのリポジトリに取り込むことができましたが、その情報はremotes/origin/masterというブランチに取り込まれており、現在のブランチであるmasterブランチには取り込まれていません。

mergeする前に、remotes/origin/masterにブランチを切り替えてみましょう。

git checkout remotes/origin/master

ファイルを確認すると、git_fetch.pyファイルがあるのが分かると思います。
確認が終わったら、元のmasterブランチに切り替えましょう。

git checkout master

それでは、remotes/origin/masterのブランチを現在のmasterブランチにマージしましょう。
コマンドは git merge <ブランチ名> でしたね。

git merge remotes/origin/master

これで現在のブランチを確認してみると、git_fetch.pyファイルが存在するのが分かります。

git pullコマンドについて

git pullコマンドは、git fetchとgit mergeを合体させたようなコマンドです。
以下のような書式で用います。

git pull <リモート名> <ブランチ名>

再びリモートリポジトリが他の人によって更新された場合を考えます。今回はgit_pull.pyファイルを追加します。
24.PNG

このリモートリポジトリの変更をローカルリポジトリで取得しましょう。以下のコマンドで取得できます。

git pull origin master

以上のコマンドで、masterブランチにgit_pull.pyファイルが追加されているのが確認できると思います。

プルリクエストについて

それではプルリクエストについて解説します。

プルリクエストとは、自分の変更したコードをリポジトリに取り込んでもらうように依頼する機能になっています。

複数人で開発を行う際に、全員が好きなようにコードの変更をしてしまえば、今まで動いていたコードが動かなくなったり、質の悪い変更をしてしまうことがありますよね。

それを防ぐためにあるのがプルリクエストです。

自分の変更をリモートのリポジトリにマージする際に、他の人にレビューを依頼するようにお願いします。これがプルリクエストです。

それではプルリクエストまでの流れを以下に図解しました。
25.PNG

実際にプルリクエストの行ってみましょう。

以下のコマンドでブランチを最新の状態にしましょう。

git pull origin master

ブランチを最新の状態にした後は、ブランチを切っていきます。lesson_pull_requestブランチを作成しましょう。

git checkout -b lesson_pull_request

git checkoutに-bオプションをつけると、新しいブランチを作成しながらHEADを変更することができます。

次のようにlesson.pyファイルを変更しましょう。

lesson.py
print('Hello GitHub')
print('create new branch')
print('lesson pull request')

lesson.pyをステージングエリアに追加します。

git add lesson.py

lesson.pyをローカルリポジトリにコミットしましょう。

git commit -m "add lesson pull request"

それではリモートリポジトリにlesson_pull_requestブランチをプッシュします。

git push origin lesson_pull_request

それではこちらからGitHubを開きます。

先ほどプッシュしたリモートリポジトリから、Pull requestのタブを開きましょう。

27.PNG

Compare & pull requestを押した後、プルリクエストの題名と本文を入力し、Create pull requestボタンを押せばプルリクエストの完了です。

プルリクエストが完了したあとは、右側のReviewersからレビュアーを選択し、プルリクエストをレビューしてもらう人を選択しましょう。

以上でプルリクエストは終了です。

終わりに

ここまででGitHubマニュアルは終了です。お付き合い頂きありがとうございました。

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

git 自分用

gitからcloneしてcheckout

git clone xxx
git checkout -b ブランチ名

gitをpushするまで

git add .
// VSCodeで不要なコミットを取り除く
git commit -m "コメント" -m "コメント2"
git push origin ブランチ名

他の人のソースを入れる

git pull origin develop

自分のソースをリセットする

git checkout HEAD ファイル名
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

gitconfigのsystemにデフォルトで設定されいるalias

小ネタというかただのメモ。ちなみにMacだと /usr/local/git/etc/gitconfig にsystemのgitconfigがあります。

git config --syetem --list で出るalias部分

Gitをサイトからダウンロードしたときに設定されているalias。パッケージマネージャ経由だと設定されていない?ようなので[alias]の部分だけメモ。結構便利でよく使っている。

[alias]
    s = status
    a = !git add . && git status
    au = !git add -u . && git status
    aa = !git add . && git add -u . && git status
    c = commit
    cm = commit -m
    ca = commit --amend # careful
    ac = !git add . && git commit
    acm = !git add . && git commit -m
    l = log --graph --all --pretty=format:'%C(yellow)%h%C(cyan)%d%Creset %s %C(white)- %an, %ar%Creset'
    ll = log --stat --abbrev-commit
    lg = log --color --graph --pretty=format:'%C(bold white)%h%Creset -%C(bold green)%d%Creset %s %C(bold green)(%cr)%Creset %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative
    llg = log --color --graph --pretty=format:'%C(bold white)%H %d%Creset%n%s%n%+b%C(bold blue)%an <%ae>%Creset %C(bold green)%cr (%ci)' --abbrev-commit
    d = diff
    master = checkout master
    spull = svn rebase
    spush = svn dcommit
    alias = !git config --list | grep 'alias\\.' | sed 's/alias\\.\\([^=]*\\)=\\(.*\\)/\\1\\\t => \\2/' | sort

git aliasで設定されているalias(systemだけでなくglobalやlocalの設定も含む)が表示されるので便利です。あとはgit log系も色付けされていたりツリー表示されていたりとよく使います。

全体はこれ

[core]
    excludesfile = ~/.gitignore
    legacyheaders = false # >git 1.5
    quotepath = false

[user]
#   name = your name
#   email = your@name

[mergetool]
    keepBackup = true

[push]
    default = simple # [ matching | simple ]

[color]
    ui = auto
    interactive = auto

[repack]
    usedeltabaseoffset = true # >git 1.5

[alias]
    s = status
    a = !git add . && git status
    au = !git add -u . && git status
    aa = !git add . && git add -u . && git status
    c = commit
    cm = commit -m
    ca = commit --amend # careful
    ac = !git add . && git commit
    acm = !git add . && git commit -m
    l = log --graph --all --pretty=format:'%C(yellow)%h%C(cyan)%d%Creset %s %C(white)- %an, %ar%Creset'
    ll = log --stat --abbrev-commit
    lg = log --color --graph --pretty=format:'%C(bold white)%h%Creset -%C(bold green)%d%Creset %s %C(bold green)(%cr)%Creset %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative
    llg = log --color --graph --pretty=format:'%C(bold white)%H %d%Creset%n%s%n%+b%C(bold blue)%an <%ae>%Creset %C(bold green)%cr (%ci)' --abbrev-commit
    d = diff
    master = checkout master
    spull = svn rebase
    spush = svn dcommit
    alias = !git config --list | grep 'alias\\.' | sed 's/alias\\.\\([^=]*\\)=\\(.*\\)/\\1\\\t => \\2/' | sort

[include]   # as of 1.7.10 https://github.com/git/git/commit/9b25a0b52e09400719366f0a33d0d0da98bbf7b0
    path = ~/.gitcinclude
    path = .githubconfig
    path = .gitcredential

#[github]
#   user =
#   token =

[diff]
    # git does copy/rename *detection*. if you want it to track copies/renames:
    # http://stackoverflow.com/questions/1043388/record-file-copy-operation-with-git
    # renames = copies

[diff "exif"]
    textconv = exif
[credential]
    helper = osxkeychain
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

You need to resolve your index first

git branchマージがエラーとなって、他のブランチに切り替えたい時、こんなエラーメッセージが出ます。

「You need to resolve your index first.」

もしchangesファイルcommitしない時、
commit必要があれば、commitをクリックして、
逆に、全てのファイルはDiscard changeを行います。

続きまして、Terminalを開いて、コマンドします。
まずは自分のプロジェクトの格納場所を探して開いて

cd gitProject
git checkout gitBranch
git reset --merge

そうしたらば、Switch branchできます。

以上です。備忘録として書きます。

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

git pull する前のcommitを確認したい

git reflog

git reflog コマンドでheadの動きの履歴が確認できます。

使用ケースとしては git pull すると以前になかったバグが発生してしまったけど、git pullする前はどの commit にいたっけ?... みたいな時に便利だと思います。

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

AWS Git Codecommit で環境に応じて資格情報を分ける方法

前提

OS: windows 10

課題

windows資格情報にログイン情報を登録するが、Codecommitの場合、環境ごとのURLが一緒になってしまう。
結果、1つの環境しか登録できない。

それを防ぐため、configファイルを編集し別ものとして登録する。

方法

資格情報を消す

既に登録されているものが優先されて使用されてしまうため、資格情報を消します。

  1. windowsタスクバーの検索から、資格情報にアクセス
    image.png

  2. windows資格情報に行き、codecommitのURLが振られている資格情報を削除する。
    image.png
    image.png

configファイルの編集

プロジェクトごとの.git/config内を追加編集する。

例. AWSの環境番号が12345678の場合
以下を追加する。

.git/config
[credential]
    namespace = 12345678

ログイン情報の設定

  1. gitクライアント等でfetchコマンドを入力する。
  2. 資格情報を入力する窓が表示される。設定値を入力する。

確認

資格情報に、指定された番号で登録されていればOK
image.png

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

AWS Git Codecommit で環境に応じて資格(ログイン)情報を分ける方法

前提

OS: windows 10

課題

windows資格情報にログイン情報を登録するが、Codecommitの場合、環境ごとのURLが一緒になってしまう。
結果、1つの環境しか登録できない。

それを防ぐため、configファイルを編集し別ものとして登録する。

方法

資格情報を消す

既に登録されているものが優先されて使用されてしまうため、資格情報を消します。

  1. windowsタスクバーの検索から、資格情報にアクセス
    image.png

  2. windows資格情報に行き、codecommitのURLが振られている資格情報を削除する。
    image.png
    image.png

configファイルの編集

プロジェクトごとの.git/config内を追加編集する。

例. AWSの環境番号が12345678の場合
以下を追加する。

.git/config
[credential]
    namespace = 12345678

ログイン情報の設定

  1. gitクライアント等でfetchコマンドを入力する。
  2. 資格情報を入力する窓が表示される。設定値を入力する。

確認

資格情報に、指定された番号で登録されていればOK
image.png

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

Git mergeする時に迷ったこと 〜現在の変更と入力側の変更〜

Githubでmerge作業をしようとした際プルリクがToo complexとなった時の話

GitHubでプルリクを出すと、”These conflicts are too complex to resolve in the web editor”となった。
(こうなるのは変更点が多すぎるとなる様子)

解決に参考にした記事:https://kei178.me/programming/235/

こういう場合はVS Codeでmerge出来る

手順

VS Codeの対象プロジェクトのターミナル上で
$ git merge master
この時mergeしたいブランチが自分の現在のブランチからdevelopブランチの場合は

$ git merge origin/develop
(この時 git merge developでない点注意!)
(仮にこうした場合ターミナルに

merge: develop - not something we can merge
Did you mean this?
        origin/develop

と表示される)
なのでorign/develpとすれば良いことがわかる。

次に
$git status
を実行すると以下のようにコンフリクトしている箇所がわかるようになる

Unmerged paths:
  (use "git add/rm <file>..." as appropriate to mark resolution)
        both modified:   css/main.css
        deleted by us:   css/style.css
        both modified:   footer.php
        both modified:   sidebar.php
        both modified:   single.php

上記のようにコンフリクトが起きている箇所が表示される。
ここまで実行すると該当のコンフリクトのあるファイルに
スクリーンショット 2020-11-19 6.01.30.png

上記画像のように「現在の変更」と「入力側の変更」が表示される

ここで今回のポイント

現在の変更:自分のこれまでのブランチで入力していた内容
入力側の変更:mergeしようとしていたブランチ側(今回ならdevelop)で入力されている内容

自分のブランチの内容をそのまま使いたければ現在の変更を取り込む
developブランチの内容をそのまま使いたければ入力側の変更を取り込む

必要な部分を選びたければdeleteキーを使用して手動で削除していけば良い

変更が終わったら

git add .
git commit -m '変更をコミット'
git push origin ブランチ名

でプッシュし、再度Github上でプルリクしてマージすればOK

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

GitHub Desktopから卒業したい人のためのGitコマンド まとめ

GitHub Desktopに慣れ親しんできたけど、そろそろ卒業したくなったみなさまへ。きっと、私のほかにもいるはずだ! と思ったので基本動作と思われるものを中心にまとめます。

ブランチ

一覧を見る

$ git branch # ローカルブランチ
$ git branch -r # リモートブランチ
$ git branch -a # すべてのブランチ

作成・変更・削除する

$ git branch [ブランチ名]  # 作成
$ git checkout [ブランチ名]  # 変更
$ git branch -d [ブランチ名]  # 削除

ブランチ関連は、このあたりでやっていること。
git03.png

変更ファイル

一覧を見る

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

        modified:   package-lock.json
        modified:   package.json
        new file:   src/components/Message.vue
        new file:   src/components/Rate.vue
        modified:   src/router/index.js

要するに、この部分の情報。
Group 7.png

コミットの対象にする

$ git add .

.はカレントディレクトリを意味する。この場合、画像でいう以下の操作に近い。なお、git addの後、空欄区切りでファイル名を指定していくこともできる。
git01.png
addがやっていることに関しては「ステージングエリア」の理解も必要。以下が可愛い。

また、コマンドのバリエーションについては以下も参考にしたい。

差分を確認する

$ git diff HEAD # 前回コミットとの差分

GitHub Desktopでいう、これ。
スクリーンショット 2020-11-19 2.20.18.png
コマンドを打つと、差分は以下のように表示される。
スクリーンショット 2020-11-19 2.21.14.png
diff関連のコマンドは非常に豊富なので、以下を参照。

コミットする

$ git commit -m "コメント"

ここで言う"コメント"は以下の部分。
commit.png

note: コミットのコメントを書き換える

undoで戻って、編集したくなる人は覚えておきたい。

$ git commit --amend

プッシュする

$ git push -u origin [ブランチ名] # そのブランチではじめてのpush
$ git push # そのブランチで2回目以降のpushなら省略できる

originとはリモートリポジトリが置いてある場所を意味する。上のコマンドはoriginのどのブランチにプッシュするか、という意味。

pushはこのボタンでやっていること。
git02.png

さいごに

とにかく、普段使っている操作、目についたものから列挙してみました。常日頃から「それってGitHub Desktopで言う、どれよ」という熟練者には伝わらない切なさも感じていたので、これを機にGitHubへの理解を深めたいなと思い、まとめました。少しでもお役に立てることがあればうれしいです。

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