やなぎにっき

学んだことの記録

過去のコミットの内容を変更する

Gitで過去のコミット内容を変更したときのメモ

やりたいこと

Gemfileなどの設定ファイルの最終行を入れ忘れるのをよくやってしまう。

Githubにpushした後に気づいたので、既にこの状態でコミットを数回かけてしまっている。 f:id:yana_g:20201111154757p:plain 修正したものを新たにコミットしてもいいんだけど、できるならGemfile追加したコミットで修正したい。

やったこと

git rebase -iを使って修正した。

1.修正したいコミットの1つ前のコミットハッシュを取得

$ git log -n 10 --oneline --reverse
897dd2a (master) first commit
31a7030 gemfileにkaminari追加
30c612d ページング処理実装
319ec6e kaminari_config.rb作成
6bfb404 default_per_page設定
3556732 (HEAD -> pagination, origin/pagination) 並び順の指定

※過去10個分のコミットを1行ずつ表示している


2.上記の 31a7030のコミットを修正したい場合
$ git rebase -i 31a7030

vimで表示されるコミットのうち、対象のコミットだけpickupをeditにして保存&終了

3.当該コミットがワークブランチに展開される
f:id:yana_g:20201111160119p:plain この状態で修正する
修正が終わったらgit addで変更をステージングする(忘れがち)
git commit --amendを実施することで、元のコミットを修正できる


4.最後にgit rebase --continueでコミットを修正される
同時に元の作業コミットに戻る f:id:yana_g:20201111160939p:plain

この場合通常のpushしてもエラーが出てしまうので、-fで強制プッシュを行う。
無事に修正できました f:id:yana_g:20201111160907p:plain


コミットは修正できましたが、同じ過ちを繰り返さぬようVSCode側の設定でtrimFinalNewlines をtrueにして自動で改行を入れてくれるように設定しました。



参考
git-rebase - 過去のコミットを修正したい(コミット分割、内容訂正・追加) akikumo_tea - Ruffnote (ラフノート)
VS Codeで行末やファイル末尾の空白文字を削除するには:Visual Studio Code TIPS - @IT

関連
なぜ最終行に改行が必要なのか - komagataのブログ

不要なファイル.DS_Storeを.gitignoreで管理対象外にする

Githubでローカルリポジトリをリモートにpushしたところ、.DS_Store という不要なファイルまでアップロードされてしまっていた。

.DS_StoreをGitの管理対象外にするために調べたこと・対応したことのメモ。

.DS_Storeとは

mac側で作成された独自の形式の隠しファイル。

すべてのフォルダに自動的に作成される。

やりたいこと

pushしてしまった.DS_Storeをリモートリポジトリから削除する

これ以降も.DS_Storeを管理対象外にする

手順

Gitリポジトリに .gitignore ファイルを作成する

$ touch .gitignore


.gitignoreファイルにgitに上げたくないファイルを記載する

.DS_Store

記載例は一般的な .gitignore 設定 が参考になる


既にGit管理しているファイルはただ.gitignoreに追加してもキャッシュが残っているため反映してくれない。

そのためキャッシュを削除する必要がある。

$ git rm -r --cached .

 -r : ディレクトリを再帰的に削除する→下層にあるディレクトリにも適用される

 —cached : インデックスからの削除だけを実行する(ワークツリーのファイルは保持する)


commitの結果.DS_Storeのファイルが削除されている。

$ git add .
$ git commit -m ".gitignore追加"

結果

[master 2bad78c] .gitignore追加
 3 files changed, 1 insertion(+)
 delete mode 100644 .DS_Store
 create mode 100644 .gitignore
 delete mode 100644 views/.DS_Store


githubの画面上を確認してみても.DS_Storeが表示されなくなっていた👌


参考

コマンドライン引数を扱う際の注意点(ARGV.getopts)

フィヨルドブートキャンプではRubyのプラクティスの一つに「Rubyでlsコマンドをつくる」という課題がある。

その課題作成中にコマンドライン引数を扱う際につまずいたことのメモ。

やりたいこと

ls.rbコマンドのオプションとディレクトリ名を引数として受け取りたい。

コマンド:$ ls.rb -alr <ディレクトリ名>

参照したこと

ARGVとは

ARGVをプログラム中に呼び出すことでコマンドライン引数を配列で受け取ることができる。

Object::ARGV (Ruby 2.7.0 リファレンスマニュアル)

サンプル

  • プログラム
p ARGV
  • 実行シェルコマンド
$ ruby sample.rb foo bar baz
["foo", "bar", "baz"]

ARGVでオプションを取得するには

optparse を require することにより、OptionParser::Arguable の機能を使うことができる。
ARGV.getops(short_opt, *long_opt)でオプションを保持したHashを得ることができる。 OptionParser::Arguable#getopts (Ruby 2.7.0 リファレンスマニュアル)

サンプル

  • プログラム
#!/usr/bin/env ruby
require 'optparse'
params = ARGV.getopts('a:b:', 'foo', 'bar:')
p params
  • 実行結果
$ ruby sample.rb -a 1 --foo --bar xxx
{"a"=>"1", "b"=>nil, "foo"=>true, "bar"=>"xxx"}

試したことと分かったこと

まずp ARGVでどのような値が取得できるか見てみる。

#!/usr/bin/env ruby
require 'optparse'

p ARGV
$ ls.rb -a    
["-a"]
$ ls.rb -arl   
["-arl"]
$ ls.rb -a test
["-a", "test"]

配列で取得できた。

次はオプションを取得するためにgetoptsを使ってみる。

~省略~

p ARGV.getopts('alr')
$ ls.rb -a
{"a"=>true, "l"=>false, "r"=>false}
$ ls.rb -arl
{"a"=>true, "l"=>true, "r"=>true}
$ ls.rb -a test
{"a"=>true, "l"=>false, "r"=>false}

オプションは取得できたが、オプションの後のディレクトリ名は取得できない。

getoptsの後にARGVを取得してみる。
$ ls.rb -a test を実行すれば {"a"=>true, "l"=>false, "r"=>false, "test"}のように取得できるのではないか。

~省略~

p ARGV.getopts('alr')
p ARGV
$ ls.rb -a test
{"a"=>true, "l"=>false, "r"=>false}
["test"]

引数は取得できたが、予想に反してtestだけだった。 試しにgetoptsの前でもARGVを参照してみる。

~省略~

p ARGV
p ARGV.getopts('alr')
p ARGV
$ ls.rb -a test
["-a", "test"]
{"a"=>true, "l"=>false, "r"=>false}
["test"]

どうやら、AGRV.getoptsを実行すると、ARGVから取得した値を削除する模様。
るりまには「破壊的な変更」のような記載はないけど、自身をパースがこのような挙動の説明になるっぽい……?

今回は以下のようにAGRV.getoptsでオプションの引数を取得した後にAGRVディレクトリ名として取得することで解決した。

options = ARGV.getopts('alr')
input_dir = ARGV

CSS 親子要素

CSSの親・子要素の関係が分からなくなるので自分なりにまとめた。

 

  HTML

<div id="test">
<div class="parent">親要素
<div class="child">子要素
<div class="grandchild">孫要素</div>
</div>
</div>
</div>

CSS

.parent {
  width: 100px;
  height: 100px;
  padding: 10px;
  background: lightgray;
}

f:id:yana_g:20200703124802p:plain

parentセレクタfont-weight: bold;を追加。 font-weightプロパティは子以下の要素にも反映される。

f:id:yana_g:20200703125015p:plain

続いてparentセレクタborder: solid 2px gray;を追加。 borderは非継承プロパティなので子以下に反映されない。

f:id:yana_g:20200703125445p:plain

子要素childセレクタborder:inherit;を追加すると親のプロパティを引き継ぐ。

.parent {
  width: 100px;
  height: 100px;
  padding: 10px;
  background: lightgray;
  font-weight: bold;
  border: solid 2px gray;
}
.child {
  border:inherit;
}

f:id:yana_g:20200703125814p:plain

孫要素grandchildセレクタborder:inherit;を追加すると親のプロパティを引き継ぐ。(画像・コードは省略)

参考:スタイルの継承-CSSの基本

paddingも子要素に継承されない。borderと同じように子要素にpadding:inherit;をつけると親要素の設定を引き継ぐ。

.parent {
  width: 100px;
  height: 100px;
  padding: 10px;
  background: lightgray;
}
.child {
  background:darkgray;
}
.grandchild{
  background:gray;
}

f:id:yana_g:20200703130454p:plain