20191112のGitに関する記事は12件です。

Git ブランチの復活

「あれ?作ったはずのブランチが見つからない。。。
 間違って消しちゃった!」

そんな経験ありませんか?
「ブランチ管理がいい加減だからそんなことになるんだ!」
そう思ってた僕もとうとうやってしまいました。
結構差分が大きいコミットだったんですが、まだ元に戻せる可能性は残ってるみたいです。

方法

GtiにはReflogというのがあって、ローカルリポジトリでのHEADの変遷を全て記録しています。
このReflogを使って戻したい時点のコミットを探せば元に戻すことができます。
Reflogの履歴はgit reflogコマンドで見ることができます。

Terminal
$ git reflog
f5fd3ef39 (HEAD -> feature/switch_enabled_address) HEAD@{0}: rebase finished: returning to refs/heads/feature/switch_enabled_address
f5fd3ef39 (HEAD -> feature/switch_enabled_address) HEAD@{1}: rebase: mail有効化の切り替えを非同期通信に変更
2f1138f9b (origin/master, origin/HEAD, master) HEAD@{2}: rebase: checkout master
b3946b35a HEAD@{3}: checkout: moving from master to feature/switch_enabled_address
2f1138f9b (origin/master, origin/HEAD, master) HEAD@{4}: merge origin/master: Fast-forward
c8ae0c424 HEAD@{5}: checkout: moving from feature/switch_enabled_address to master
b3946b35a HEAD@{6}: rebase -i (finish): returning to refs/heads/feature/switch_enabled_address
b3946b35a HEAD@{7}: rebase -i (squash): mail有効化の切り替えを非同期通信に変更
57080d0bf HEAD@{8}: rebase -i (start): checkout HEAD~9
a9a5a5894 (fork/feature/switch_enabled_address, test/switch_enabled_address_circle) HEAD@{9}: checkout: moving from test/switch_enabled_address_circle to feature/switch_enabled_address
a9a5a5894 (fork/feature/switch_enabled_address, test/switch_enabled_address_circle) HEAD@{10}: Branch: renamed refs/heads/feature/switch_enabled_address to refs/heads/test/switch_enabled_address_circle

例えばこれは僕のReflogなんですが、大まかにいって下記のような形式をしてます。
HEAD{n}のnはHEADが変わった回数を記録していて、0が今のHEADで数が大きくなるほど過去のHEADを表します。
僕の例でいうと、現在のHEAD、HEAD{0}のコミット番号はf5fd3ef39でrebaseをした直後であることがわかります。

rebase前にコミットを戻してみましょう。

僕の例では3回前のHEAD、HEAD@{3}が、rebase前のHEADになります。Reflogから、masterブランチからfeature/switch_enabled_addresscheckoutした直後です。

あとはブランチを作成する要領で、

Terminal
$ git switch -c revive HEAD@{3}

これで元に戻すことができました。

Reflogについて

Reflogはかなり便利で、master@{one.week.ago}みたいな指定もできるみたいです。
詳しくは、https://git-scm.com/docs/git-reflogに解説があるので読んでみてください。

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

CLOCで日本語ファイル名をGit上で比較する

はじめに

CLOCというツールでステップ数を集計しようとしたら、日本語のファイル名でエラーになりました。
それを解決した話。

結論

まず、結論から。
環境はMac。
エラー内容はこんな感じ。

$ cloc --git --diff release feature
fatal: pathspec 'myrepository/\343\202\212\343\203\274\343\201\251\343\201\277\343\203\274.md' did not match any files
Failed to create tarfile of files from git. at /usr/local/Cellar/cloc/1.84/libexec/bin/cloc line 4713.

圧縮ファイルが作れないって言ってる。
文字化け感満載。
下記コマンドをローカルリポジトリで一度流せば解決。

$ git config --local core.quotepath false

CLOCについて

オープンソースのステップ数計測ツールです。
単純な計測以外にも、比較やgitにも対応しています。

この情報が必要な人は既にCLOC使い始めてると思うので・・・公式サイトは以下です。
http://cloc.sourceforge.net/

公式サイトの更新が滞ってるようなので、コマンドのヘルプかソースみた方が良さげです。

原因

ソース中に git ls-tree --name-only -r release でファイルリスト取得している部分があるのですが、ここで文字化けしてました。
解決策はこちらを参考にさせて頂きました。
https://dev.classmethod.jp/tool/git/git-avoid-illegal-charactor-tips/
ありがとうございます。

感想

情報があまり見当たらなかったので、動かしながらデバッグしました。
perlはじめてでしたが、言語はなんであれソース動かすの楽しい。

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

CLOCとGitで日本語ファイル名のファイルを比較する

はじめに

CLOCというツールでステップ数を集計しようとしたら、日本語のファイル名でエラーになりました。
それを解決した話。

結論

まず、結論から。
環境はMac。
エラー内容はこんな感じ。

$ cloc --git --diff release feature
fatal: pathspec 'myrepository/\343\202\212\343\203\274\343\201\251\343\201\277\343\203\274.md' did not match any files
Failed to create tarfile of files from git. at /usr/local/Cellar/cloc/1.84/libexec/bin/cloc line 4713.

圧縮ファイルが作れないって言ってる。
文字化け感満載。
下記コマンドをローカルリポジトリで一度流せば解決。

$ git config --local core.quotepath false
$ brew install gnu-tar
$ export PATH=/usr/local/opt/gnu-tar/libexec/gnubin:$PATH

再起動したら再びエラーになると思うので、環境変数は.bash_profile等に追記しても良いと思います。

CLOCについて

オープンソースのステップ数計測ツールです。
単純な計測以外にも、比較やgitにも対応しています。

この情報が必要な人は既にCLOC使い始めてると思うので・・・公式サイトは以下です。
http://cloc.sourceforge.net/

公式サイトの更新が滞ってるようなので、コマンドのヘルプかソースみた方が良さげです。

原因

その1

ソース中に git ls-tree --name-only -r branch_name でファイルリスト取得している部分があるのですが、ここで文字化けしてました。
解決策はこちらを参考にさせて頂きました。
https://dev.classmethod.jp/tool/git/git-avoid-illegal-charactor-tips/
ありがとうございます。

その2

解決したと思いきや、こんなメッセージが表示されるように・・・。

Usage:
  List:    tar -tf <archive-filename>
  Extract: tar -xf <archive-filename>
  Create:  tar -cf <archive-filename> [filenames...]
  Help:    tar --help

tarのオプションが間違ってる雰囲気。
-vオプションで詳細みてみると-Aオプションを指定しているようだが、tar --help-Aオプションの記載はない。
下記記事を参考にさせて頂いた所、解決しました。
https://hacknote.jp/archives/8951/
ありがとうございました。

感想

情報があまり見当たらなかったので、動かしながらデバッグしました。
perlはじめてでしたが、言語はなんであれソース動かすの楽しい。

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

Git fatal: Unknown index entry format

備忘録的に。
間違ったshellを動かしてgitレポジトリをぶっ壊してしまったとき。(.git ファイルなど隠しファイルにも影響を与えてしまった場合。。)

$ git checkout .

を行なっても下記エラー。

fatal: Unknown index entry format x56axxxx

ほなとりあえずローカルレポジトリのremoteとの紐付け消すか、としたら

$ git remote rm origin
error: non-monotonic index .git/objects/pack/pack-12kjneffselfnwj3jwjk3wdnsdjknajw3dwdsjnd.idx
error: non-monotonic index .git/objects/pack/pack-12kjnadwselfnwj3jwjk3wdnsdjknajw3dwdsjnd.idx
error: non-monotonic index .git/objects/pack/pack-12kjnefffslfnwj3jwwk3wdnsdjknajw3dwdsjnd.idx
error: non-monotonic index .git/objects/pack/pack-12kjneawselfnwj3jwjk3wdnsdjknajw3dwdsjnd.idx
error: non-monotonic index .git/objects/pack/pack-12kjneffselfnwj35wjk3wdnsdjknajw3dwdsjnd.idx
error: non-monotonic index .git/objects/pack/pack-12kjneffssdfnwj3jwjk3wdnsdjknajw3dwdsjnd.idx
error: non-monotonic index .git/objects/pack/pack-12kjneffawdfnwj3jwjk3wdnsdjknajw3dwdsjnd.idx

うおお。なにこれ。

$ git fsck --full
error: inflate: data stream error (invalid distance too far back)
error: unable to unpack header of .git/objects/04/4c9cedaw427385a0aae914bea384fc45ba03236

したら同じようなログが1000行以上でてきた。これはもうちょっと解析できるレベルではない。

新しく同じ名前のディレクトリをつくって git remote add してから git pull しても下記。

$ git pull origin master
error: refs/heads/master does not point to a valid object!
error: inflate: data stream error (invalid block type)
error: unable to unpack xxxdc4ae26830ab44ae2746c52865556a4d993c1 header
error: inflate: data stream error (invalid block type)
error: unable to unpack xxxdc4ae26830ab44ae2746c52865556a4d993c1 header
fatal: loose object xxxdc4ae26830ab44ae2746c52865556a4d993c1 (stored in .git/objects/xx/xxx4ae26830ab44ae2746c52865556a4d993c1) is corrupt

おそらくだが .git までshellで変更してしまったから、もうこれは直せないと感じ、
下記を試しました。現状のリモートディレクトリの .git を持ってきて自分のローカルのものと置き換える。

Git: “Corrupt loose object”

The fix
Execute these commands from the parent directory above your repo (replace 'foo' with the name of your project folder):

Create a backup of the corrupt directory:

cp -R foo foo-backup

Make a new clone of the remote repository to a new directory:

git clone git@www.mydomain.de:foo foo-newclone

Delete the corrupt .git subdirectory:

rm -rf foo/.git

Move the newly cloned .git subdirectory into foo:

mv foo-newclone/.git foo

Delete the rest of the temporary new clone:

rm -rf foo-newclone

これで元に戻りました。
ありがとうStackOverflow.
今回、ローカルだったのでぶっ壊れてもなんとかなりましたが、これをリモート側でやってしまったら結構取り返しのつかない大事件になるところでした。
リモート先で実験する場合はmasterレポジトリをbackupした先で行うことが必要だと再実感できてよかったです。

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

Gitを使ってみよう

入社して1か月半経ったある日…

上司:bust_in_silhouette:<この案件はGitを使うから覚えてね~
a-takano<わかりました。(Gitってなんぞ?:rolling_eyes:

a-takano<本格的にbacklogを使うようになってきたな…

とりあえずサルでもわかるGit入門から始めよう!:monkey:
こっちもわかりやすいなー→【イラストで覚える】初心者のためのGitとGitHub用語集
随時更新していこう。

Gitってなんぞや?

分散型バージョン管理システムの1つ。読みは「ぎっと」。
ファイルの状態を更新履歴として残せて、過去の状態に戻せたり編集した部分との差が見れる→ファイル名に_aとか日付とか付けなくてもいい!

同じファイルを2人以上で編集してアップロードをしようとしてもアラートが出るから、「間違って他の人の編集内容を上書きしちゃった!:scream:」なんてこともない。

リポジトリってなんぞや?

ファイルやディレクトリの状態を記録するとこ。変更履歴は格納され記録されていく。
普段の作業はローカルリポジトリで、作業が完了したらリモートリポジトリに
プッシュ(=アップロード)する。

リモートリポジトリ

自分の手元外にあるリポジトリ。他の人と共有するために使う。
個人開発でも使える。
Cloudとはちょっと違う。

ローカルリポジトリ

自分の手元にあるリポジトリ。自分のマシン内に作られる。

リポジトリを共有しよう!

Gitをインストール後諸々設定して最初にやったのが【リモートリポジトリのクローン】だったので、これから記述する。

リモートリポジトリのクローン

他の人が作ったり変更したリモートリポジトリを、丸ごと複製(=クローン)して自分の手元に置くこと。

リモートリポジトリにプッシュ

ローカルリポジトリで加えた変更を、リモートリポジトリで共有すること。
つまりアップロードすること。

リモートリポジトリからプル

リモートリポジトリからローカルリポジトリへダウンロードすること。
リモートリポジトリの方が変更履歴が新しかったら、その内容を取り込む。

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

Git操作まとめ 〜Gitのコミット履歴確認

この記事では、Ubuntu18.04LTSにインストールしたGit(version 2.17.1)を使用しています。

チームではもちろんですが、個人での使用であっても今までのコミット履歴を確認する必要が出てきます。
そうすることで、誰が、いつ、どんな意図でその作業をしたのを理解することができ、効果的に開発を進めていくことができるようになります。

履歴確認

履歴を確認するには、以下のコマンドを使用します。

git log

実際に使ってみます。

git log

commit 76d180faf45d1da99905f225830a07f7b9c31603 (HEAD -> master)
Author: xxxxxx <xxxxxxxx@gmail.com>
Date:   Tue Nov 12 08:30:47 2019 +0900

    initial commit

このように表示されます。
1行目・・・commit コミットナンバー
2行目・・・Author コミットした人の名前とメールアドレス
3行目・・・Date コミットした日付
4行目・・・コミットコメント

この形式で、新しいコミットが前のコミットの上に表示されます。


履歴の簡易表示

git logで履歴を見ると、初めのうちはコミット数も少なくコミットの詳細を見ることができるため便利ではありますが、場合によっては「もっと簡略化したものでいいから、履歴をザッと確認したい」というときも出てきます。
そういうときは、onelineオプションをつけることで、コミットごとに1行表示で履歴を見ることができます。

git log --oneline
76d180f (HEAD -> master) initial commit

本記事目次ページ

Git操作まとめ

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

DataikuのプラグインテンプレートをDataikuの外から作れないか試してみる

はじめに

Dataikuではプラグイン開発を行う際にリモートのgitからcloneすることができます。
ところがリポジトリに中身がない(あるいはreadmeしかない)プロジェクトをcloneしようとすると「The plugin's definition is invalid」なんて怒られてしまいます

ということでプラグインとgit連携の基本的な流れは...

  1. Dataikuで空のプラグインを作成
  2. リモートにpush
  3. 他のDataiku環境からリモートのリポジトリををclone

ということになると思います。
ここで、

  1. リモートで先にgitリポジトリ作成
  2. 各Dataiku環境からclone

というのができないかなとちょっと気になったので調べました。

公式の説明

公式によれば次のように書いてあります
公式ドキュメント

A DSS plugin is made of a number of components, each component being a specific new kind of object in DSS.

The plugin is described by a plugin.json file

なんとなくplugin.jsonがあればDataikuプラグインとして認識されそうです

プラグインの中身

Dataiku上でemptyなプラグインを作り、plugin.jsonを確認してみますと、構成は次のようになっておりました。

plugin.jon
{
 "id":プラグインの識別子,
 "version":バージョン番号,
 "meta":{
  "label":インターフェース上の表示名,
  "description":プラグインの説明,
  "icon":アイコン画像(FontAwesome 3.1 iconsに含まれるもの),
  "licenseInfo":ライセンス情報,
  "url":プラグインについての参考URL,
  "tags":[
    プラグインにつけるタグ情報
  ]
 }
}

なんとなくこの辺りを書いてリポジトリの一番上に置いておけばそのままプラグインとして認識してもらえそう

試してみる

plugin.jsonを以下のようにして試しに作成し、リモートのgitリポジトリにおきます

plugin.jon
{
 "id":"Qiita_TEST",
 "version":"1",
 "meta":{
  "label":"Qiita Test Plugin",
  "author":"test author",
  "description":"テストプラグイン",
  "icon":"icon-thumbs-up",
  "licenseInfo":"ライセンス",
  "url":"https://qiita.com/komugiko",
  "tags":["test"]
 }
}

Plugins Development画面から「New DEV PLUGIN」を選択し、Source をGit、Import methodをEntire repositoryに設定してcreateします

結果

無事に設定内容を読み込んでプラグインとしてクローンできました。
ということで、毎回空のプラグインを作ってリモートにpushしなくても、中身を与えたplugin.jsonを直接リポジトリに埋め込んでおけば空のプラグインとして認識されるようです。

もう少しプラグイン構成を調べてみて、Dataiku外の環境からプラグインを開発できないかなと思ったり...

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

DataikuのプラグインテンプレートをDataiku外から作れないか試してみる

はじめに

Dataikuではプラグイン開発を行う際にリモートのgitからcloneすることができます。
ところがリポジトリに中身がない(あるいはreadmeしかない)プロジェクトをcloneしようとすると「The plugin's definition is invalid」なんて怒られてしまいます

ということでプラグインとgit連携の基本的な流れは...

  1. Dataikuで空のプラグインを作成
  2. リモートにpush
  3. 他のDataiku環境からリモートのリポジトリををclone

ということになると思います。
ここで、

  1. リモートで先にgitリポジトリ作成
  2. 各Dataiku環境からclone

というのができないかなとちょっと気になったので調べました。

公式の説明

公式によれば次のように書いてあります
公式ドキュメント

A DSS plugin is made of a number of components, each component being a specific new kind of object in DSS.

The plugin is described by a plugin.json file

なんとなくplugin.jsonがあればDataikuプラグインとして認識されそうです

プラグインの中身

Dataiku上でemptyなプラグインを作り、plugin.jsonを確認してみますと、構成は次のようになっておりました。

plugin.jon
{
 "id":プラグインの識別子,
 "version":バージョン番号,
 "meta":{
  "label":インターフェース上の表示名,
  "description":プラグインの説明,
  "icon":アイコン画像(FontAwesome 3.1 iconsに含まれるもの),
  "licenseInfo":ライセンス情報,
  "url":プラグインについての参考URL,
  "tags":[
    プラグインにつけるタグ情報
  ]
 }
}

なんとなくこの辺りを書いてリポジトリの一番上に置いておけばそのままプラグインとして認識してもらえそう

試してみる

plugin.jsonを以下のようにして試しに作成し、リモートのgitリポジトリにおきます

plugin.jon
{
 "id":"Qiita_TEST",
 "version":"1",
 "meta":{
  "label":"Qiita Test Plugin",
  "author":"test author",
  "description":"テストプラグイン",
  "icon":"icon-thumbs-up",
  "licenseInfo":"ライセンス",
  "url":"https://qiita.com/komugiko",
  "tags":["test"]
 }
}

Plugins Development画面から「New DEV PLUGIN」を選択し、Source をGit、Import methodをEntire repositoryに設定してcreateします

結果

無事に設定内容を読み込んでプラグインとしてcloneできました。
ということで、毎回空のプラグインを作ってリモートにpushしなくても、中身を与えたplugin.jsonを直接リポジトリに埋め込んでおけば空のプラグインとして認識されるようです。

もう少しプラグイン構成を調べてみて、Dataiku外の環境からプラグインを開発できないかなと思ったり...

おまけ

Dataikuのpersonal API keyがあればPycharmからプラグイン開発ができるらしいです
公式ドキュメント

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

先祖返りが発生する理由がわからないIT部のPMがGit / GitHub を整理してみた

Git / GitHubがよくわからなかったので整理してみた。
元々の整理の発端はなぜベンダーが納品してくる成果物が頻繁に先祖返りするのかわからなかったから。GitHubで管理しているというが、なぜだ〜って感じ。調べてみたところ、Subversionと昔使われていたツールにしても最近使われているGitHubないしは類似サービスにしても人に依存する部分もあり先祖返り完全防止機能はないことがわかった(管理を間違えれば先祖返りはありうるということ)。
GitHub はコマンドベースで動く Git が使いやすくなっているサービスということも理解できた(メールで言うとGmail的な感じ)。この手の話題はネット上の資料だと日英問わず間違っている物や不完全な説明も多そうで、実際のところ私のまとめもただしいかどうかわからない状況。様々な文献をベースに図式化してみると次のようになった。

git.png

・リモートレポジトリと呼ばれるものが正、作業用としてローカルレポジトリがある。
・ローカルにはUpstreamブランチ、Trackingブランチと呼ばれる中継がある(一つのブランチ名が両方を指していることがあるが、別々にすることもでき、このことについて言及されていない記事が多い)
・実際のローカルで作業を行うブランチは中継目的のUpstreamブランチ、Trackingブランチとは異なる
・pull = fetch、merge の同時実行
・pullとrebaseの違いは他の記事を参照、履歴の残し方の問題でrebaseだと簡略化されたイメージ(履歴は少なくなるがバグが発生するとどこが原因だか追いづらい)

先祖返り問題・・・結局なんで?防止策?

これについてはネット検索してもいまいち確実な理由がわからなかったが、いくつかのパターンは考えられた。
・fetch+merge/pull/rebaseからmerge, pushで確定するまでの間で同一ファイルの複数作業(複数人または同一人だが別々の端末など)が発生の原理原則
・コード数が多いファイルで起きやすい(コード数が小さいファイルに分割されている環境では同一人物ないしは異なる人物が一つのファイルで同時多発的に作業をするケースが少なくなるため(競合発生が低くなり、commmitの撤回(reset)による影響度合いも必然的に少ない))
・意図してreset を流すが(その後必要でpushし上書きもするが)、意図された事項以外も元に戻ってしまうケースがありうる
・merge/push時にエラー/警告がでて解決が面倒である際に
git push 時に-f ないしは --force で強制上書きできる(複数人作業でローカルにコピーをしまくりこれをされると先祖返りが極めて発生しやすい)

防止策:
・一つのソースファイルで全てを抱え込まないようにする
・まずは単独作業者自身においてこまめにcommitさせる
・互いに声をかけ短時間の間隔で、こまめにmerge/pull, pushする
 
ベンダーに依頼するとなるとこんな感じですかね。。。?
 
参考資料
https://qiita.com/wann/items/688bc17460a457104d7d
https://teratail.com/questions/79531
https://kray.jp/blog/git-pull-rebase/
https://blog.codecamp.jp/git_rebase
https://www.clear-code.com/blog/2016/9/2.html
https://www.ricksoft.jp/blog/archives/9483/
https://dev.classmethod.jp/tool/git/development-flow-with-safty-merge/
https://frasco.io/why-you-should-stop-using-git-rebase-535fa30d7e25
https://qiita.com/seri1234/items/e651b3e108a695a92809
https://yu8mada.com/2018/08/11/how-to-confirm-and-set-up-tracking-branches-in-git/
https://codeday.me/jp/qa/20190104/109718.html

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

rebaseとは

IMG_20181025_170659.jpg

ブランチ切って作業をしているときに、他の人がmasterに変更を加えていた場合に、シレッと今のmasterの先頭から自分がそのブランチを切って作業しているような状態にしたい。という場合はrebaseする。

手順

git checkout master
masterにチェックアウト
git pull
まずはmasterを最新の状態に進める
git checkout topic
topicに戻る
git rebase master
今のtopicをぎゅいんと最新にしたmasterの先にくっつける
(⑤masterのどこかのcommitでconflictした場合は、それを修正してrebaseを繰り返す)

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

Gitについて学んだことまとめ

Githubを使ったことがあるし、なんとなく知っているけど、ちゃんとは理解できていないエンジニア未経験の私が
有識者の方々よりいただいたロードマップにそってGitについて学んだことをまとめたものです。

目次

  1. Gitとは
  2. Gitの操作方法
  3. GitHubでのPRやMergeの仕方
  4. Git Flow, Github Flowとは
  5. 今後の課題

今回の学習のゴール

  1. 代表的なコマンドがわかる(add, commit, push, rebase, merge, checkout)
  2. GitHubでPRやMergeの仕方がわかる
  3. Git Flow, GitHub Flowを知る

1. Gitとは

プログラムのソースコードなどの変更履歴を管理するシステム
いつ、誰が、ファイルのどの部分を変更したか記録でき、以前のファイルの状態に戻すことができる

2. Gitの操作方法

Gitの操作方法については、主にLearn Git Branchingを使用し学習しました。

主なコマンド

コマンド.jpg

add

指定したファイルの変更履歴をステージングエリアに追加し、変更履歴を残す準備する

$ git add <ファイル名>

commit

ローカルリポジトリへ変更履歴を記録する

$ git commit -m "<メッセージ>"    # 何を変更したか等のメッセージをつけて、変更履歴を保存する

diff

2つのテキストファイルを比較し、ファイル間の差分を出力する

$ git diff <比較するファイル1> <比較するファイル2>

push

ローカルリポジトリの変更履歴をリモートリポジトリへアップロードする

$ git push origin <ブランチ名>    # どのブランチをプッシュするか指定する

clone

コミットの差分を辿って全ての変更を取得できる

$ git clone <URL>    # コピーしたいリポジトリのURLを指定

branch

分岐の連なりの記録のこと
変更履歴を分岐して記録したり、合流させてそれぞれの変更内容を統合したりできる

$ git branch <ブランチ名>    # ブランチを作成
$ git checkout <ブランチ名>    # 作業ブランチを変更

merge

分岐したブランチを一つにまとめる
マージしたブランチのコミットが残る

$ git merge <ブランチ名>

merge.jpg

Rebase

ブランチを一つにまとめる
リベースしたブランチが、一本の連続したコミットに整形できる

$ git rebase <ブランチ名>

rebase.jpg

HEADにまつわるコマンド

HEADとは、チェックアウトされているコミットを指す時の呼び方で、今どのコミットで作業しているかを意味する

^(ハット)オペレータ

$ git checkout master^    # masterの最初の親コミットへ移動できる
$ git checkout master^^    # masterのおじいちゃんコミットへ移動できる

~ オペレータ

$ git checkout HEAD~4    # 4つ前のコミットへ移動できる
$ git branch -f master HEAD~3    # masterブランチをHEADから数えて3個前の親コミットへと強制(force)的に移動することができる
$ git branch -f master <コミット名>    # masterブランチを指定のコミットへと強制的に移動することができる

git reset

ブランチのポインタを元に戻すことで変更のキャンセルができる
履歴を上書きし、前のコミットがなかったかのようにできる

$ git reset HEAD~1    # ブランチのポインタを1前に戻す

revert

変更を巻き戻して、その変更をリモート上で他の人と共有する際に使用

$ git revert HEAD

cherry-pick

HEAD(現在の位置)の下にコピーしたいコミットを持ってくることができる

$ git cherry-pick <コミット名> <コミット名>...    # コピーするコミットは複数指定可能

インタラクティブrebase -i

インターフェイス(vimなどのテキストエディタの中でファイルが開く)上で、どのコミットがrebase対象の下にコピーされるかを確認できる

$ git rebase -i HEAD~

tag

重要なコミットに印(タグ)をつけることができる

$ git tag v1 <コミット名>    #v1というタグを指定するコミットにつける

describe

複数あるコミットの中を移動する際に、現在いる位置を示してくれる

$ git describe <参照>    # ブランチ, タグ, コミットハッシュ等を指定する
<タグ>_<コミット数>_g<ハッシュ>  # コマンドの結果

3. GitHubでPRやMergeの仕方

GitHub公式のIssue とプルリクエストでのコラボレーションを参考にし学習しました。

Pull Requestとは

  • 他者に対してあなたがGitHub上のリポジトリ内のブランチにpushした変更を知らせること
  • 同一リポジトリのブランチ間で、pull requestを作成でき、変更の承認を依頼することができる
    • リポジトリをフォーク※し、そのフォークに変更を加えた場合には、pull requestを作成することで上流リポジトリにその変更の承認を依頼することができる
  • Pull Requestでは、変更を加えたファイルとmergeするファイルの差分(diff)をレビューしたり、コメントしたりできる
  • Pull Requestで変更の承認がおりればmergeすることができる(リポジトリに対してpushできるユーザーであればmerge可能)

※フォークとは、ユーザが管理するリポジトリのコピーのこと
オリジナルのリポジトリに影響を与えることなくプロジェクトへの変更を行いたい時に使用

merge conflict

  • 競合するコミットを持つブランチをmergeしようとしたときに生じるものをmerge conflictという
  • merge conflictは、GitHub上のconflict editorか、もしくは、コマンドラインとテキストエディタを使用して解決する

参照:マージコンフリクトへの対処

4. Git Flow, GitHub Flowとは

Git Flow 及び GitHub Flow について自分なりに調べてまとめました。
どちらもGitにおけるリポジトリのモデルのことを指します。

Git flow

Git flowでは、masterとdevelopの2つのブランチを軸に、それらを補助するfeature, release, hot-fixの3つのブランチを使い分けて開発を行う

masterブランチ:リリースしたデータを置いておくブランチ
developブランチ:開発を行うためのブランチ
featureブランチ:開発を行うためのブランチで、個々の機能の実装やバグの解決を行う
releaseブランチ:リリース前に微調整を行うブランチ
hot-fixブランチ:リリース後に、緊急の修正対応をするためのブランチ
Git flow.jpg

このようにそれぞれのブランチに役割を持たせることで、ワーキングスペースが明確になり効率の良い開発を進めていくことができる

GitHub Flow

git flowが簡略化されたもので、masterを軸に、説明的な名前(機能追加やバグ修正など)を付けたブランチを作成して開発を行う

  1. ローカルの作業ブランチで作業が完了後、リモート上の同じブランチにpush
  2. GitHub上でpull requestを出し、コードレビューをもらう
  3. 必要があればローカルでコードを修正し、再度リモートへpush
  4. コードレビュー及び修正が完了後、masterにmergeする

5. 今後の課題

  • プルリクのレビューの仕方やアンチパターンについて知る

参考

Learn Git Branching
Issue とプルリクエストでのコラボレーション
git flowとは一体どういうものなの?イメージしにくいgit flowを徹底解説!
git flowとgithub flowとは?その違いは? - Qiita
Gitを最大限に活用できる「Git flow」で、効率よく開発を進めよう!
GitHub Flow 図解

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

Git操作まとめ 〜Gitの基本コマンド(git add / git commit / git status)

この記事では、Ubuntu18.04LTSにインストールしたGit(version 2.17.1)を使用しています。

Gitを操作する上で、基本的なコマンドの3つを書いていきます。
これらは、開発を進めていく際に常に心がけておく最低限のものです。

個人でバージョン管理を行う上で3つの階層が存在します。開発履歴をそれらの階層を行ったり来たりさせることで、履歴を残して行けます。その3つの階層はいくつかの呼び方がありますが、以下のものになります。

  • 作業ディレクトリ(ワークツーリー)
  • ステージングエリア(インデックス)
  • リポジトリ(ローカルリポジトリ)

コミット状況の確認

Gitの管理下にあるディレクトリの作業ディレクトリとステージングエリアの状態を確認するには、以下のコマンドを使用します。

git status
実行結果
ブランチ 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)

上記の実行結果では、README.mdというファイルが履歴の追跡対象になっていないことが示されました。
次項目のステージングを行うことで追跡対象に追加することができます。


ステージング

作業ディレクトリで開発を進めたものを、ステージングエリアに移動させることを「ステージングする」といい、以下のコマンドで実行することができます。

任意のファイルやディレクトリをステージングする場合
git add ファイル名
全てのファイルやディレクトリをステージングする場合
git add .

追跡対象になっていなかったファイル"README.md"をステージングしてみます。

git add README.md
git status
ブランチ master

No commits yet

コミット予定の変更点:
  (use "git rm --cached <file>..." to unstage)

    new file:   README.md

これで、ステージングエリアにファイルREADME.mdが追加され、コミットの準備が整いました。
引き続いて、commitコマンドを使ってみます。


コミット

ステージングエリアに追加されたファイルをコミットするまでが、履歴追跡の一連の流れになります。以下のコマンドでコミットが可能です。

git commit "コミット名"
コミットメッセージを一行に納める
git commit -m "コミット名"

実際にコミットしてみます。

git commit

コミットコマンドを実行すると、テキストエディタが起動してコミットメッセージの入力を求められます。
Ubuntuではデフォルトで起動するエディタは"nano"ですが設定を変更することで、Vimなどのエディタに変更できます。

初めてのコミットなので、コミットメッセージを"initial commit"として登録します。

登録したあと、確認してみます。

git status
ブランチ master
nothing to commit, working tree clean

これで、コミットできたことが確認できました。


本記事目次ページ

Git操作まとめ

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