20190719のGitに関する記事は5件です。

[memo] git rebaseでdevelopの変更を取り込む

概要

  • プルリクエストを作成するときはgit rebasedevelopの変更を取り込んでからプッシュしてほしい

なんで?

デグレが起きるかもしれないから

方法

1. 作業ブランチにチェックアウト

git checkout 作業ブランチ

2. developの変更を取り込む

変更を取り込んだあとにコンフリクトがあれば修正する

git rebase origin/develop

3. プッシュする

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

[Git] git log の日時を見やすくする

TL;DR

標準出力は日付部分のみを抜粋している。

$ git log
Wed Jul 10 15:59:02 2019 +0900
Tue Jul 16 02:36:47 2019 +0000

$ git log --date=iso-local
2019-07-10 15:59:02 +0900
2019-07-16 11:36:47 +0900

$ git log --date=format-local:'%Y/%m/%d %H:%M:%S'
2019/07/10 15:59:02
2019/07/16 11:36:47

説明

git log で表示される日時は (おそらく多くの日本人にとって) 読みにくい。

$ git log
Wed Jul 10 15:59:02 2019 +0900 # JST
Tue Jul 16 02:36:47 2019 +0000 # UTC

そこで --date オプションでフォーマットを指定する。iso-local (ISO 8601 形式) が読みやすい。

$ git log --date=iso-local
2019-07-10 15:59:02 +0900
2019-07-16 11:36:47 +0900

フォーマットに独自のものを指定したい場合は format-local を使う。format ではなく format-local を使うことで、タイムゾーンがローカルに統一される。

$ git log --date=format:'%Y/%m/%d %H:%M:%S'
2019/07/10 15:59:02
2019/07/16 02:36:47

$ git log --date=format-local:'%Y/%m/%d %H:%M:%S'
2019/07/10 15:59:02
2019/07/16 11:36:47

参考

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

TECH  DAY 6

勉強した項目: git, Github, scraping
時間: 10:00
内容:

*学習アウトプットです。なにぶん間違いなんかもあります。気をつけますがその際はご指摘いただけますと幸いです*

[Git]

Gitはソースコードの変更履歴、バージョン等を記録するツール
最大の特徴は、分散型の名の通り、ローカル環境に、全ての変更履歴を含む完全なリポジトリの複製が作成されるということである。    
(リポジトリ:複数のデータや情報などが体系立てて保管されているデータベース)

[Github]

Gitの仕組みを利用して、世界中の人々が自分のプログラムコードやデザインデータなどを保存、公開することができるようにしたウェブサービスの名称である。
エンジニアの履歴書のような役割

[git clone]

外部のサーバーにあるGitで管理されたソースコードを自分のパソコン(ローカル環境)にダウンロードするコマンド
git clone リポジトリURL ディレクトリ名という形でターミナルで実行する

[lsコマンド]

lsコマンドはlinuxコマンドの一つ
lsコマンドを使用すると、現在のディレクトリにあるファイルを表示することができる、lsは「list segments」の略

[bundlerによるgem管理]

bundlerを利用してインストールしたgemは、Railsの各プロジェクトではなく、Rubyのバージョンごとにある保存場所にインストールされる
bundle show [gemの名前]というコマンドを実行でどこに保存されているのか確認することができる

[bundle execコマンド]

bundle exec は2つ以上のrailsアプリケーションを同じバージョンのRubyを利用して作成している際に必要となるコマンド
→同じRubyのバージョンで複数のアプリケーションを開発していると、同じ名前のgemでもアプリケーションごとにバージョンが異なることがあるため

[スクレイピング]

ウェブサイト上のHTMLからある特定のデータを抜き出す処理のこと
→ 

  • の中にある値を取り出すこと

    [Mechanize]

    スクレイピングを行うためのGem
    Mechanizeクラスが使えるようになり、スクレイピングをするための様々なメソッドが存在する

    Gemfileの最後の行に

    Gemfile
    gem 'mechanize'
    

    記載する。
    Gemfileに記述されたGemをインストールするにはターミナルでコマンドbundle installを打ち込むことを忘れないようにする。

    [getメソッド]

    Mechanizeクラスのインスタンスメソッド
    get("スクレイピングしたいウェブサイトのURL")と引数にURLの文字列を指定することで、そのURLのウェブサイトのHTMLを取得できる

     agent = Mechanize.new
      page = agent.get("http://naru-taka-kokua.com") # naru-taka-kokua.comのHTMLを取得
    

    pageは単なるHTMLの文字列ではなくそのウェブサイトのHTMLの情報を持ったMechanize::Pageオブジェクトである

    [searchメソッド]

    getメソッドで取得したページの情報が入ったオブジェクトに対して使用
    →取得したウェブサイトのHTML情報の中から指定したHTML要素の内容を検索できる

    elements = Mechanize::Pageオブジェクト.search('セレクタ')
    

    引数のセレクタとはCSSのようにHTMLのタグの要素名を指定し、'h1'や'li a'のような指定
    クラス名でも.hogeのように指定することができる

      agent = Mechanize.new
      page = agent.get("http://naru-taka-kokua.com/")
      elements = page.search('h2')
     # h2要素を検索
      puts elements
    

    [inner_textメソッド]

    searchメソッドで得られたHTML情報のテキストを取得したい場合、inner_textメソッドを使う

     agent = Mechanize.new
      page = agent.get("http://naru-taka-kokua.com/")
      elements = page.search('h2 a') # h2要素の下のa要素を検索
      puts elements
    

    [get_attributeメソッド]

    aタグ要素のHTMLはリンク先のURLを値とする属性hrefを持っているので、このHTMLの属性の値を取得したい場合、get_attributeメソッドを使う

      agent = Mechanize.new
      page = agent.get("http://naru-taka-kokua.com/")
      elements = page.search('h2 a') # h2要素の下のa要素を検索
    
      elements.each do |ele|
        puts ele.get_attribute('href') # puts ele[:href]としても良い
      end
    

    [スクレイピングの手順 簡潔に]

    1/Mechanizeクラスのインスタンスを生成
    2/Mechanizeクラスのインスタンスメソッドget(情報を取得したいウェブサイトのURL)で、ウェブサイトのHTML情報を取得
    3/欲しいデータのあるタグ要素をsearchメソッドで指定して取得
    4/取得したタグ要素のHTML情報にたいしてinner_textメソッド、またはget_attributeメソッドを使って欲しい値を取得

    実際のHTMLを確認には、[command] + [option] + [u]を押してソースコードを表示できる

    element = page.search('.etc div) の etcがクラス名

    [atメソッド]

    searchメソッドと同じようにセレクタを指定して、該当するHTML要素を取得するメソッド
    →searchメソッドのように該当するものが複数あってもすべて取得はせず、最初の1つしか取得しない

    ele.get_attribute('src')は、ele[:src] と書くことも可能

    [reload!]

    コンソール起動中にコードを修正・追記した際、コンソールはリアルタイムで変更内容を反映してくれないので再起動する必要がある
    →これをreload! コマンドを実行すると毎回exitの再起動しなくてもコンソールがコードの変更内容を読み込んでくれる

    [first_or_initializeメソッド]

    whereメソッドとともに使うことで、whereで検索した条件のレコードがあればそのレコードのインスタンスを返し、なければ新しくインスタンスを作るメソッド

    [rails generate migrationコマンド]

    テーブルにカラムを追加したり、削除するようなテーブルの構造を変えたいときもマイグレーションファイルを作成する

    ターミナル
      $ bundle exec rails g migration AddRateToApps
      # => マイグレーションファイルの作成
    

    これだと、Appsのマイグレーションファイルが作られる

    [add_column]

    add_columnをマイグレーションファイルのchangeメソッド内に書くとカラムの追加ができる

    add_column :テーブル名, :カラム名, :カラムの型
    

    複数のカラムを追加する場合は段落分けて記述する

    add_column :テーブル名, :カラム名, :カラムの型
    add_column :テーブル名, :カラム名, :カラムの型
    add_column :テーブル名, :カラム名, :カラムの型
    

    [remove_column]

    changeメソッドではカラムを追加だけでなく削除もできる

    remove_column :テーブル名, :カラム名, :カラムの型
    

    必ず、マイグレーションファイルを変更した場合は、ターミナルにて rake db migarate を実行する

    [while文を抜け出すのは途中にbrakeを記載する]

    [orderメソッド]

    データベースからデータ取得時にデータをどう並び替えるかというのが指定できる

     モデル名.order('カラム名 順序')
    
    実行例 詳細
    App.order('id DESC') idを降順でAppデータ取得
    App.order('id ASC') idを昇順でAppデータ取得

    [limitメソッド]

    データをいくつ取得するかというのが指定できるメソッド

    データをいくつ取得するかというのが指定できるメソッド
    
    App.limit(20)   #Appを20件まで取得する
    

    orderメソッドを使うことによって最新順にデータを取り出すこともできる

    @app = App.order('id ASC').limit(20)
    

    appテーブルをidで昇順に並べ替え、20件だけを取得し、それらを@appという変数に代入している

    [findメソッド]

    findメソッドは引数に指定したidにあたる作品情報を1件だけ取得
    →もし、そのidにあたる作品が存在しない場合、エラーが発生

    例:idが10のappを取得する

    App.find(10)
    # idが10のAppモデルのインスタンスが取得
    # or
    # idが10のAppモデルのインスタンスがない場合エラー
    

    [rake routesコマンド]

    アプリケーションでアクセスできるHTTPリクエストの一覧を見ることのできるコマンド
    →HTTPリクエストのメソッド(GET, POSTなど)とパス、それに対応するコントローラとアクション名が確認できる

    表示されるコマンド例

    ターミナル
    app GET  /apps/:id(.:format)                     apps#show
    

    GETで/app/:id(:format)というHTTPリクエストが呼ばれた時にappsコントローラーのshowメソッドが呼ばれる

    [params[:id]]

    HTTPリクエストが送られると、パス(/products/20)から作品idを取得することができる

    作品idはパラメーターとして自動的にparamsというハッシュ型の変数に格納されコントローラに送られ、キーは/products/:idのid、バリューはアクセスしたパスの:idの箇所に一致する数字となる

    [LIKE句]

    あいまいな文字列の検索をすることができるもので、whereメソッドと一緒に使う

    使い方→

    モデルクラス名.where('検索するカラム名 LIKE(?)', "検索するキーワード")
    

    曖昧な文字列について

    文字列 意味
    % 任意の文字列(空白文字列含む)
    _ 任意の1文字

    % と _ の位置に注意して

    実行例 詳細
    where('title LIKE(?)', "a%") aから始まるタイトル
    where('title LIKE(?)', "%b") bで終わるタイトル
    where('title LIKE(?)', "%c%") cが含まれるタイトル
    where('title LIKE(?)', "d_") dで始まる2文字のタイトル
    where('title LIKE(?)', "_e") eで終わる2文字のタイトル

    [resourcesメソッド]

    対象となるリソース名(コントローラ名)を指定するだけで、Railsのリソースの7つのアクションで記載した7つのアクション名に対してのルーティングが自動的に設定できる

    config/routes.rb
     Rails.application.routes.draw do
      resources :app: 
    

    ターミナルにて bundle exec rake routes コマンドを実行すると7つのルーティングが確認できる

     Prefix Verb   URI Pattern               Controller#Action
         apps GET    /apps(.:format)          apps#index
              POST   /apps(.:format)          apps#create
      new_app GET    /apps/new(.:format)      apps#new
     edit_app GET    /apps/:id/edit(.:format) apps#edit
          app GET    /apps/:id(.:format)      apps#show
              PATCH  /apps/:id(.:format)      apps#update
              PUT    /apps/:id(.:format)      apps#update
              DELETE /apps/:id(.:format)      apps#destroy
    

    [resourcesメソッドのネスト]

    config/routes.rb
    resources :apps do
      resources :reviews
    end
    

    [form_for]

    form_forは、特定のモデルを編集・追加するためのフォームを生成するヘルパーメソッド
    →特定のテーブルにレコードだけを新規作成、更新するときに利用する

    <%= form_for(モデルクラスのインスタンス) do |f| %>
    …
    <% end %>
    

    form_for内で使うメソッドは、f.htmlタグ名 :カラム名の形で指定

    メソッド 用途
    f.label labelのlabelタグを表示 
    f.text_field textのinputタグを表示
    f.date_select モデルで設定したフィールドをselectタグで選べるようにして表示
    f.check_box checkboxのinputタグを表示
    f.number_field numberのinputタグを表示
    f.submit submitのinputタグを表示

    一部です。

    [form_forとform_tag]

    form_forform_tag どちらを使うべきかは、基本的にモデルの有無で判断する

    form_for→入力フォームで入力するデータのモデルがある (投稿フォームなど)
    form_tag→入力するデータが特にモデルを持っていない (検索フォームなど)

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

ディレクトリ名を指定してクローンする方法

  • 環境
    • Windows10
    • git version 2.18.0.windows.1

参考 : git cloneしてきたプロジェクトの名前を変えてクローンしてくる方法 - Qiita

ディレクトリ名を指定しないとリポジトリ名になる

$ cd {クローンしたい場所}
$ git clone https://github.com/user/{リポジトリ名}.git
$ ls
{リポジトリ名}

ディレクトリ名を指定すると指定したディレクトリ名になる

$ cd {クローンしたい場所}
$ git clone https://github.com/user/{リポジトリ名}.git {ディレクトリ名}
$ ls
{ディレクトリ名}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Gitのブランチがdetached fromになってしまった時の失敗した対応方法

  • 環境
    • CentOS Linux release 7.6.1810 (Core)
    • git version 1.8.3.1
    • xfc4-terminal 0.8.7.4

事象 : 現在のブランチにdetached fromと表示される

# 何だ?
$ git branch
* (detached from origin/feature/branchA)
  feature/develop

# 何だ何だ?
$ git branch --contains=HEAD
* (detached from origin/feature/branchA)

# 今のブランチはどこへいった?
$ find .git/refs/heads/
.git/refs/heads/
.git/refs/heads/feature
.git/refs/heads/feature/develop

しかも1回コミットしちゃった

# コミットした時よく見るとdetached HEADとかいってたのに
$ git commit -m "問題コミットのコメント"
[detached HEAD e4ab2e5] 問題コミットのコメント
 8 files changed, 258 insertions(+)
 create mode 100644 project/src/main/java/jp/co/Hsitory.java
 create mode 100644 project/src/main/java/jp/co/logic/HsitoryLogic.java
 create mode 100644 project/src/main/java/jp/co/logic/impl/HsitoryLogicImpl.java

# プッシュしてエラーになったのに
$ git push
fatal: You are not currently on a branch.
To push the history leading to the current (detached HEAD)
state now, use

    git push origin HEAD:<name-of-remote-branch>

# 更にプッシュしてエラーだったのに・・・
$ git push --set-upstream origin feature/branchA
error: src refspec feature/branchA does not match any.
error: failed to push some refs to 'https://github.com/user/repo.git'

# なんかログに出てたからつい放置してしまった(コミットしたんだから出るさ)
$ git log
commit e4ab2e5
Author: ponsuke <ponsuke@mail.com>
Date:   Wed Jul 10 18:13:31 2019 +0900

    問題コミットのコメント

commit 3407420
Merge: 05bc343 d532a4b
Author: ponta <50603053+ponta@users.noreply.github.com>
Date:   Wed Jul 10 11:20:17 2019 +0900

    Merge pull request #5 from feature/branchB

    Feature/branchB

# そしてこのハッシュ変だ!
$ git name-rev e4ab2e5
e4ab2e5 undefined

原因 : HEADがブランチではなくコミットを指しているから

detached HEAD から脱出する方法を git の内部構造から探る - Qiita

# HEADの流れを見てみる
$ cat .git/logs/HEAD
# 省略
d532a4b e0fdb37 ponsuke <ponsuke@mail.com> 1562661447 +0900   checkout: moving from branchB to feature/develop
e0fdb37 e0fdb37 ponsuke <ponsuke@mail.com> 1562662611 +0900   checkout: moving from feature/develop to feature/branchA
e0fdb37 e0fdb37 ponsuke <ponsuke@mail.com> 1562721493 +0900   checkout: moving from feature/branchA to feature/develop
e0fdb37 3407420 ponsuke <ponsuke@mail.com> 1562726844 +0900   checkout: moving from feature/develop to origin/feature/branchA
3407420 e4ab2e5 ponsuke <ponsuke@mail.com> 1562750011 +0900   commit: 問題コミットのコメント

# branchAの流れを見てみると・・・何か・・・ユーザ名をタイポったようだ・・・
$ cat .git/logs/refs/remotes/origin/feature/branchA
0000000 e0fdb37 ponsuke <ponsuke@mail.com> 1562662653 +0900   update by push
e0fdb37 3407420 onsuke <onsuke@82e9656b4223.(none)> 1562726194 +0900    fetch: fast-forward

失敗した対応 : もとのブランチまで戻そうとして、コミットした変更内容まで戻してしまった。

# これまでの操作を確認する
$ git reflog
e4ab2e5 HEAD@{0}: commit: 問題コミットのコメント
3407420 HEAD@{1}: checkout: moving from feature/develop to origin/feature/branchA
e0fdb37 HEAD@{2}: checkout: moving from feature/branchA to feature/develop
e0fdb37 HEAD@{3}: checkout: moving from feature/develop to feature/branchA
e0fdb37 HEAD@{4}: checkout: moving from branchB to feature/develop
# 省略

# コミットした変更内容は消さないように戻したかった
$ git reset --hard HEAD@{0}
HEAD is now at e4ab2e5 問題コミットのコメント

# まだ、detachedだなぁ
$ git branch
* (detached from origin/feature/branchA)
  feature/develop

# そっか、コミット後に戻ったからまだ変なんだ、と思った
$ git status
# HEAD detached from origin/feature/branchA
nothing to commit, working directory clean

# コミットしちゃっているからdiffも出ないし
$ git diff HEAD
$

# もういっこ戻そう!
$ git reset --hard HEAD@{1}
HEAD is now at 3407420 Merge pull request #5 from feature/branchB

# ん?
$ git status
# HEAD detached at origin/feature/branchA
nothing to commit, working directory clean

# コミットした変更内容まで戻してしまった!
$ git diff HEAD
$

# あ~~~もう変更内容はない〜
$ git log
commit 3407420
Merge: 05bc343 d532a4b
Author: ponta <50603053+ponta@users.noreply.github.com>
Date:   Wed Jul 10 11:20:17 2019 +0900

    Merge pull request #5 from feature/branchB

    Feature/branchB

この後、もう一度実装し直してコミット&プッシュしたらもとのブランチ(origin/feature/branchA)に無事変更が入りました。

次回への反省 : 落ち着こう

  1. プッシュ時を振り返って
    1. fatal: You are not currently on a branch.(現在ブランチ上にいません)って言われているんだから考えよ、やり方も教えてくれてるんだからメッセージ読もう

git push origin HEAD:master
現在の分岐を、originリポジトリ内のリモート参照に一致するmasterにプッシュします。この形式は、ローカル名を考慮せずに現在のブランチをプッシュする場合に便利です。
Git - git-push Documentation

  1. 戻し作業の前を振り返って
    1. 間違ってコミットした変更対象のファイルをどっかに退避してからもとのブランチまで戻して、退避したファイルを戻す
    2. まず、もとのブランチをチェックアウトして、間違えたコミットをチェリーピックしてもできたかも
  2. コミットまで戻しちゃった時を振り返って
    1. git reset --hardは取り消せるらしい
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む