#きちんとGitを使ってみる
これまでちょこちょことGitは使っていたけれど、せいぜい「Webストレージ」くらいの意識で使っていたというのが本音で、mainブランチに変更を上乗せしてpushする、、という使い方しかしてきませんでした。
人様に見せるつもりのレポジトリでそれを続けるのはさすがに恥ずかしいですし、、、ここらでちゃんとbranchを使い分けて、pullリクエストベースの管理を始めてみたいと思います。
その手始めに、これまで思考停止して打ち込んでたgitコマンドについて意味の再確認をしてみます。
#改めて。gitに関する用語と考え方。
https://docs.github.com/ja/github/getting-started-with-github/github-glossary#repository
リポジトリとレポジトリ
タイプするときの"re"positoryに引っ張られてレポジトリと読んでいたのですが、ちゃんと発音にあわすとリポジトリですね。。
座学だけでやってるとこういうのが多くなるので、注意しないとな。。
リポジトリとブランチ
樹形図上に連なるブランチ群があり、それをまとめ上げたのがリポジトリ。
以下で書きますが、リモート(github)とローカル(自分のPC)の間のやり取りはブランチ単位で行うものであり、リポジトリまるごとをダウンロードしたりアップロードするものではない、と。
思考停止してつかってたコマンド群の意味を改めて
自分のプロジェクトやコードを一通り修正完了し、一息つく前に思考停止して"git add ."、"git commit -m "XX", "git push -u origin main"の3点セットを叩く癖がついてしまっているので、改めて意味を学び直します。。
git add .
まずこいつで編集・追加したファイル群をgitの管理対象として登録して、公開したくないものが混ざり込んだらrmで消す、、という考えでしたが、結構改めないといけないですね。。
コマンドの意味
そもそもコマンドの意味は、レポジトリにファイルを「追加」する。
"."は、カレントディレクトリ配下の、.gitignoreで除外登録されているもの以外のすべてのファイル。
ワーキングディレクトリにファイルがバラバラと置かれていても、gitに管理されるのは、あくまで「追加」されたファイルだけ。
あと、新規に作ったファイルだけではなく、変更したファイルも追加しないと、commit時に取り込んでもらえない。
追従させたくないものは.gitignoreに追加しておいて、"add ."の際に追加対象からはずすという、まず全部拾ってからいらないものを弾く、という考え方をしてました。
あくまで「管理したいものを選択的にaddする」という考え方に矯正しないといけないですね。。
結局やることは変わらないでしょうけれど、心がけの問題で。
git rm --cached
”git add .”して、”git status"で追加されたファイル群見て、追加するつもりがなかったものが見つかったら、このコマンドで追加解除する、、としてました。
一方、"git reset "とすることもできると知りまして。
この2つの違いはというと、、
新規に作ったファイルを追加してコミットしようという場合は違いはないのですが、既存ファイルを変更した場合に大きな違いがでるんですね。
実際にやってみると、、
# 比較のため、内容を変えないファイル(unchanged)、変えるファイル(changed)、追加するファイル(added)を用意します。
$ git ls-files
changed_for_reset.txt
changed_for_rm.txt
unchanged_for_reset.txt
unchanged_for_rm.txt
$ date > ./changed_for_reset.txt
$ date > ./changed_for_rm.txt
$ touch ./added_for_reset.txt
$ touch ./added_for_rm.txt
$ git add .
# 準備完了
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: added_for_reset.txt
new file: added_for_rm.txt
modified: changed_for_reset.txt
modified: changed_for_rm.txt
# 新規ファイルに対してrm, resetすると?
# -> rm --cachedもresetも同じ結果になる。
$ git reset ./added_for_reset.txt
$ git rm --cached ./added_for_rm.txt
rm 'added_for_rm.txt'
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: changed_for_reset.txt
modified: changed_for_rm.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
added_for_reset.txt
added_for_rm.txt
# 既存ファイルに対してrm, resetすると?
# resetは、編集前の状態に戻す。
-> この状態commitすると、対象ファイルは編集前のバージョンの内容のままレポジトリに残る。
# rmは、レポジトリ自体から削除される。
# -> この状態でcommitすると、対象ファイルは編集前に戻るのではなく、削除になる。
# ちなみにどっちの場合も、ワーキングディレクトリには編集後の状態のファイルは残る。
$ git reset ./changed_for_reset.txt
Unstaged changes after reset:
M changed_for_reset.txt
$ git rm --cached ./changed_for_rm.txt
rm 'changed_for_rm.txt'
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: changed_for_rm.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: changed_for_reset.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
added_for_reset.txt
added_for_rm.txt
changed_for_rm.txt
オペミスリスクを考えると、resetを使うべきですね。。
指を矯正します。。
git commit -m "Comment"
ファイルをローカルにセーブする、位のつもりで叩いてました。
これは、あまり大きく改める必要がある部分はないかな、、?
実際はCommitの記載内容のルールを定めなければいけないですね。。現状はまだノーアイデア。
チケットベースで作業を管理していれば、チケットIDを入れるので確定でいいのですが、現状そこまでの管理にするつもりもないし。
git push -u origin main
ローカルのデータを、gitサーバにアップロードする、くらいのつもりで叩いてましたが、、、、
あってはいるけど、かなり無駄なコマンド叩いてました。
コマンドの意味
ローカルにある__mainブランチ__を、.git/configに登録してあるリモートgitサーバの中で「origin」という名称で登録しているものにアップロードし、さらに、「(pushが成功したら)上流ブランチとしてoriginを登録する」。
まず、アップするのは指定したbranchだけで、リポジトリ全体をまるごとアップするわけではない。
わざわざ引数にmainを取ってるのだからそりゃそうなのだけど、まったく意識してなかった。。
また"-u"の方も。
意味をちゃんと確認せずに使っていたのですが、これはが「今回使ったリモートgitサーバを、ローカルのmainブランチにとっての標準のリモートサーバ(上流ブランチ)として記憶しておけ、という意味なんですね。。
一回-uつきでcommitして、成功すれば、上流ブランチが保存されます。
それ以降は"git push"だけでリモートへのpushが完了します。
上流ブランチは、以下のように.git/configの、mainブランチ用の設定として自動登録されます。
# .git/configに以下が登録されます。
$ cat .git/config
[branch "main"]
remote = origin
merge = refs/heads/main
# コマンドで見ると、、
# remoteがリモートサーバの名称(originの具体的なurlなどの情報は、別途"remote"のセッションで定義されている)
# medgeが、リモートのどのブランチに対してマージするかの設定。
$ git config --list
branch.main.remote=origin
branch.main.merge=refs/heads/main
# あるいは。ブランチ名後部の[]の中に表示されます。
$ git branch -vv*
main 4dbbbc8 [origin/main] Comment
ちなみに以下で解除できます。
$ git branch --unset-upstream
何を、どこにpushするのか?
漠然と使っていた"git push -u origin main"は、手元のmainブランチを、リモートのoriginリポジトリのmainブランチに対してpushするというものでした。
これ、"main"をちゃんと書くことで、ローカルのどのブランチをリモートのどのブランチにpushするのか、細かく指定できるのですね。
https://git-scm.com/book/ja/v2/Git%E3%81%AE%E5%86%85%E5%81%B4-Refspec
例えば、ローカルでpatch01というブランチを作り、そこで新たに作ったファイルや変更を、リモートのmainにpushしたいなら、、
$ git push origin patch01:main
となる。
リモートとローカルでブランチの構造がチグハグになるので、この使い方をしてメリットがあるケースは今の所思いつかないけれど、一応記憶しておきます。
今日のところは
ここまで。