20190909のGitに関する記事は3件です。

プログラマー1年目の自分が辿り着いたGitまとめ その2

概要

プログラマー1年目の自分が辿り着いたGitまとめ その1
の続きです。

前回はコードの変更を記録していく、というバージョン管理の基本動作について触れたので、今回は少し発展的な動作と、リモートリポジトリの活用という段階に進んでいきたいと思います。

revertとreset

RPGで何のためにセーブするかといえば、『セーブした場所からやり直す』ためである(一概に言えないけど)。

なのでGitにも当然、"巻き戻し"に相当する操作があります。

reset - 指定したコミットを打ち消す

git reset コミット番号
と指定することで、そのコミットで変更した内容を打ち消すことが出来る。

ここで登場するコミット番号とは、コミットに割り振られている識別子のようなもの。
git logやGitHubの履歴で確認出来る「727cd618f38hd8hd38bae476...」みたいな英数字の羅列。
因みに全部書く必要は無く、最初の4文字(上記の例でいえば727c)でコミットを認識してくれます。

resetコマンドには2つの主なオプションが存在し
git reset --soft 727c
とすると、巻き戻された変更が"ステージング前"の変更として残ります(なのでadd - commitすれば復活する)。
git reset --hard 727c
とすると、変更は何も残らず完全にコミットが削除されます。
何かしらの検証のために行った変更などをまとめて巻き戻す時に使うと便利です。

revert - 指定したコミットを打ち消すコミットを作成する

resetとの違いは、あくまでも巻き戻し用の新たなコミットを作成している部分。
git logでコミットグラフを確認すると分かるが、resetと違って打ち消したコミットは残っている。
なのでresetを2連続で行うと、コードの状態としては元に戻るけどコミットは純粋に2つ増えている……みたいなことが起きる。

巻き戻したいけれど、記録としては残しておきたい時に使う(不具合が出ている状態のコードの保存など)。
resetより若干気楽だけども、上述の通りコミットグラフに巻き戻しコミットが追加されるので濫用は避けるべき。

わかりやすく変更を巻き戻してくれるreset/revertだが、指定したコミットの内容全てを巻き戻すので沢山の変更をまとめてコミットしてしまっている場合などは注意(巻き戻すことも考慮して、前回書いたようにコミットはこまめに行うべき)

add-commitのサイクルとreset/revertを使うことで、変更の記録及び巻き戻しというバージョン管理っぽいことが出来るようになります。
因みにcheckoutコマンドで擬似的に巻き戻しを行うことが可能ですが、これは次回以降の記事で紹介する予定です。

リモートリポジトリ(GitHub)

いよいよここで環境を遷移し、ローカルだけでなくリモートにコードを公開しながら作業を進める、ということを考えていきます。

ここで意識するのはGitの大きな特徴、『分散型』のバージョン管理という点です。
分散型とは文字通り複数の場所でソースコードを管理するということなので、手元のPC内のリポジトリ(ローカルリポジトリ)とは別の、遠隔リポジトリ(リモートリポジトリ)が必要になってくる。
このリモートリポジトリを介して複数の開発者が、それぞれのローカルリポジトリで行った内容を共有するという訳である。

Gitのリモートリポジトリを作成できるサービスとして最も有名なのが上にも少し登場したGitHub。
有名なライブラリとか、いわゆるオープンソースのソフトウェアとかはここでソースコードが管理及び公開されている事が多く、今は無料でプライベートリポジトリも作成できるので、業務で使う機会も多いはず。

個人開発や自己学習を行っている方は、ポートフォリオを作成するような気持ちでGitHubにコードを公開していくのがオススメです(周知の事実かもしれませんが)。

remoteとpush

という訳で、ローカルの変更をGitHubのリモートリポジトリに共有するという作業を考えていきます(GitHubでリポジトリを作成する方法などについては割愛)。

remote - 現在のローカルリポジトリにリモートリポジトリを関連付ける

まずはGitHubで作成したリモートリポジトリを、現在のローカルリポジトリの共有先として登録します。
git remote -v
とすると登録しているリモートリポジトリの一覧が確認できるので、最初はまず何も登録されていないことを確認しましょう。

その後、
git remote add [URL]
の形で登録。再び上記のコマンドを叩くことで登録されたことが分かるはずです。

注: プライベートリポジトリを登録する場合

GitHubにプライベートリポジトリとして作成していた場合は、URLにユーザ名を含める必要があります。そうするとgit remote add実行後にパスワードの入力を求められ、登録が完了します。
URLをそのまま貼って実行すると、特に何の注釈もなく「そのリポジトリは存在しません」的なエラーが出てくるので注意が必要です……

push - コミットをリモートリポジトリに共有する

前回基本サイクルの一部として紹介したpush。
このコマンドを実行することで、現在のローカルリポジトリのコミットをリモートリポジトリに共有することが出来る。

今はmasterブランチのみで作業している前提なので、前述のremoteコマンドによるリポジトリ登録及び変更のコミットが完了したら、
git push origin master
と実行。これにより、GitHubのリモートリポジトリに変更が共有されていることが確認出来るはずです。

originについて

originはリモートリポジトリにデフォルトで適用されるリポジトリ名。
pushコマンドは本来
git push [リモート名] [ブランチ名]
という指定を行うので、上述のようなコマンドになっている訳です。
なのでリモートリポジトリを複数登録するというようなことが無い限りは、originという名前についてそこまで意識する必要はありません。

一度pushを行うと、origin masterが『デフォルトのpush先』のように認識されるため
git push
だけで十分になります。
→ 因みにこれが上手くいかない方は同じくgit push origin masterとするか、git fetchで追跡ブランチを設定して下さい(追跡ブランチについては次回以降の記事で説明できればと思います)。

注: 別ブランチにおけるpush

まだブランチについては説明していないのですが、pushコマンドの危険な勘違いについて先に注釈しておきます。
初学者の方だと結構git push origin masterを定型文みたいなものだと思って使ってしまうことが多いのですが、あくまでもこのコマンドは『リモートリポジトリoriginのmasterブランチに』現在の内容をpushするという操作です。

なので別のブランチ(例:develop)に居る時にgit push origin masterとかやってしまうと、developでの変更内容がmasterにダイレクトに適用されるという酷い事故が起きるので、それだけは絶対にやってしまわないように、
git push [リモート名] [ブランチ名]
という構造を正しく理解しましょう。

因みに上記のケースではgit push origin developとするのが正しいです。
基本的にリモートに初めてpushするブランチの場合は具体的に名前を指定し、それ以降はgit pushとすれば大丈夫です。

補足 - configについて

Gitにはコミットを作成したりpushしたりする際に使用されるユーザー情報を登録することが出来ます。
git config --global user.name [ユーザー名]
git config --global user.email [メールアドレス]
という感じです。確認する場合はgit config --global user.nameのように手前で止めればOK。--globalオプションはどのローカルリポジトリでも適用されるようにする為の設定です。

この設定でメールアドレスをGitHubに設定したものと同じものにしておかないと、ローカルからのpushがリポジトリを管理している自分とは別の人によるものだと認識されてしまい、GitHubのコントリビューション(所謂芝というやつです)が更新されないので、GitHubを使う場合は必ず設定を確認しておきましょう。

まとめ

add-commitのサイクルに加え、reset/revertを使うことでコミットの追加、削除というバージョン管理の基本的な動作が行えるようになります。
ここにpushコマンドが加わることでGitHubのようなリモートリポジトリを介して自身のコードを公開するということが可能になりました。

最初はGitHubに自分の履歴がちゃんと共有されていることや、ログ及び差分が確認できるGitHubの便利な機能について触れ、慣れてみて欲しいと思います。

次回からは自分一人ではなく、複数人で一つのコードを編集する、という環境に遷移します!

前: プログラマー1年目の自分が辿り着いたGitまとめ その1
次: プログラマー1年目の自分が辿り着いたGitまとめ その3

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

プログラマー1年目の自分が辿り着いたGitまとめ その1

想定する読者層

  • プログラミング初学者の方
  • 業務でGitを使い始めた方
  • Gitについてまだ理解が曖昧、上手く使えていないという方

かく言う自分も自己学習なり業務なりである程度Gitを触ってきて、ようやく『こういうことか』みたいなのが掴めてきたので、備忘録も兼ねて初学者の方の助けになるような記事を投稿してみたいと思います。
ただ入門って言うよりは、ある程度触った方向けのものになるかも。

全4回予定です。

Gitを理解するには?

個人的にGitを触り始めた頃に分かりにくい、とっつにくいと感じていた点や理由を列挙してみると、

  • Gitって何の為にあるのか分かりにくい
  • やれること(コマンドとか)が多すぎて覚えられない
  • 競合ってなんだよ(怒)

などなど……
実際、色々調べたりしていく内になんとか上記の疑問を解決出来たのですが、Gitは本来バージョン管理という重要ではありながら単純な作業を行う為のものなのに、その多機能性から全容が把握しにくいといった印象は確かに今でも感じます。

そこで至った結論が、Gitを理解するには『環境を段階的に変化させること』が肝要なのではないかと。
→ これはつまり、「使うコマンドを限定して覚えていく」というイメージです。
 今回自分が考えた環境の遷移は以下の通り。

  1. まずはローカルリポジトリかつmasterブランチのみの作業(add, commit, status)
  2. masterのみで作業しつつ、リモートリポジトリに公開する作業(push, revert, reset)
  3. masterのみで作業しつつ、リモートリポジトリで共有しながらの作業(pull, stash, diff, log)
  4. ブランチを切りながら、リモートリポジトリで共有しながらの作業(checkout, branch, fetch, merge)

4番の環境が所謂チーム開発の環境だと思うので、『業務で使える』という観点でのゴールは此処になると思われます。
今回は1番の簡単な個人開発的環境を想定して3つのコマンドについてみていきます。

Gitの基本

まずは一応概要から。

Gitとはバージョン管理システムである。
プログラム(というかソースコード)がRPGだとしたら、Gitは内容をセーブするためのシステム(と自分は捉えています)。

そんでもって分散型管理システムでもあるので、自分トコのセーブデータと、他の人のセーブデータを別々で管理した後、その結果を合体させることが出来ちゃったりする(此処らへんが最初はイメージしづらいかも)

add, commit, status

個人的にGitの基本サイクルだと考えているのが、add→commit→pushの流れ。
pushは取り敢えず置いといて、addとcommitについて。

commit - 変更をコミットする。

Gitの要となる機能であり、上述の『内容をセーブする』に近い動作。
これを繰り返すことでコミットグラフなるものが蓄積されていき、ディレクトリ内の変更が記録されていく。

各コミットにはコミットメッセージというものが存在しており、そのコミット内で"どういう作業を行った"とかを人に読める形で記録する。
個人開発は勿論、プロジェクトによってはフォーマットなども決められてたりする。

短いコミットメッセージの場合は、-mオプションを用いて
commit -m "(コミットメッセージ)"
という形でコミットメッセージを書くと楽。

add - コミットするための変更をステージ(追加)する。

ぶっちゃけ最初はそこまで意識せず、セーブしたいなと思ったら
git add -A
commit -m "更新"
としてしまえば良いが、(個人開発はともかく)業務ではそうもいかないのでcommitとの違いを正しく把握しておく。

コミットというのはセーブデータを作る作業ですが、常にディレクトリ全体が記録される訳ではなくステージングという作業を行ったファイルの変更のみが変更を記録される。それを行うのがaddコマンド。
addの働きを理解するには以下のような状況を想定するのが丁度良いのかなと思います。

まずファイルA,B,Cがディレクトリ内に三つ存在し、それぞれに何かしらの変更を行ったとする。
でもファイルAの内容としては何かしらの機能追加、Bは不具合修正、Cは単なるリファクタリング、とかだった場合に3つのファイル全てをまとめてコミットするのはあまりよろしくない。

→これは前述の通りコミットにはコミットメッセージが存在していて、コミット毎に「何を行ったか」を明確にする必要があるから。

なのでこういったケースの時は
git add ファイルA
git commit -m "●●機能追加"
git add ファイルB
git commit -m "不具合修正"
.
.

みたいに、内容ごとにステージングとコミットを切り分けて記録していくのがベター。
こうすることで後からコミットグラフを見返したりチェックアウトした時に、Aのみに変更を行った状態・A,Bに変更を行った状態・A,B,C全てに変更を行った状態というのを別々に再現出来る。

バージョン管理という観点でも『特定の箇所に』『特定の変更を』行ったという情報でコミットが切り分けられている方が見やすく不具合調査の際などにも役立つので、一度に多くの変更を行ってしまったという場合でも、addコマンドを上手く使ってコミットを細かく切り分けていくことは重要になってきます。
→ こういうのが『コミットの粒度』って言葉で表現されることが多いので、意識しておくとより良いかもしれません。

status - 現在のワーキングツリーの状態を確認する。

最後に、個人的に基本サイクルに加えて良いと思ってるし実際一番よく叩く気がするコマンド。
変更を加えたけれどまだステージング(add)してないファイルや、ステージングしたけどコミットしてないファイルなどを一覧で確認出来るコマンドです。

その他にもstatus(状態)の名の通り色々な情報が書いてあるので
心配性な人はgit statusを叩きまくる癖をつければ良いと思います。

まとめ

これだけ?って思うかもしれませんが、まずはこの3つを覚えて、ローカルでかつmasterのみでの作業が問題なく出来るようになるのが大切な1ステップ目だと思います!

特にコミットを細かく分割することやメッセージをしっかり書くこと、というのは業務でも大切なことなので個人開発でも意識して行うのが重要です。

次回は2番の環境に移行して、リモートリポジトリを活用する段階に入っていく予定。

次: プログラマー1年目の自分が辿り着いたGitまとめ その2

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

Git関連の参考URL

個人用のメモです。
僕が初学者なので、初学者の人が読んでわかるリンクを載せています。
日々更新します。
世の中に発信してくれている人達のおかげで僕もコツコツ作品作れます。
ありがとうございます。

  • GitHub登録からプッシュまでの流れ

https://qiita.com/KosukeQiita/items/cf39d2922b77ac93f51d

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