{"id":18010848,"url":"https://github.com/yokawasa/github-sandbox","last_synced_at":"2025-04-04T13:15:51.640Z","repository":{"id":66860493,"uuid":"323657869","full_name":"yokawasa/github-sandbox","owner":"yokawasa","description":"This is my personal GitHub sandbox repository, and its content is primarily based on past GitHub trainings I've done for GitHub newbies","archived":false,"fork":false,"pushed_at":"2025-03-29T06:30:49.000Z","size":1276,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-29T07:22:42.788Z","etag":null,"topics":["git","github"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yokawasa.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-12-22T15:04:45.000Z","updated_at":"2025-03-29T06:30:53.000Z","dependencies_parsed_at":"2023-03-11T00:24:17.982Z","dependency_job_id":"ba8668c9-a5be-46be-9b6d-ca89019f31ea","html_url":"https://github.com/yokawasa/github-sandbox","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yokawasa%2Fgithub-sandbox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yokawasa%2Fgithub-sandbox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yokawasa%2Fgithub-sandbox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yokawasa%2Fgithub-sandbox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yokawasa","download_url":"https://codeload.github.com/yokawasa/github-sandbox/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247182421,"owners_count":20897381,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["git","github"],"created_at":"2024-10-30T02:15:32.728Z","updated_at":"2025-04-04T13:15:51.630Z","avatar_url":"https://github.com/yokawasa.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- TOC --\u003e\n\n- [Git コンセプト](#git-%E3%82%B3%E3%83%B3%E3%82%BB%E3%83%97%E3%83%88)\n- [GitHubリポジトリ設定](#github%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E8%A8%AD%E5%AE%9A)\n- [Git 初期設定](#git-%E5%88%9D%E6%9C%9F%E8%A8%AD%E5%AE%9A)\n\t- [git config](#git-config)\n\t- [git alias](#git-alias)\n- [プルリクエスト経由でリモートmainにマージ](#%E3%83%97%E3%83%AB%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E7%B5%8C%E7%94%B1%E3%81%A7%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88main%E3%81%AB%E3%83%9E%E3%83%BC%E3%82%B8)\n\t- [git clone](#git-clone)\n\t- [git branch](#git-branch)\n\t\t- [ブランチ作成](#%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E4%BD%9C%E6%88%90)\n\t\t- [ブランチ一覧表示](#%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E4%B8%80%E8%A6%A7%E8%A1%A8%E7%A4%BA)\n\t\t- [あるブランチに移動](#%E3%81%82%E3%82%8B%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%AB%E7%A7%BB%E5%8B%95)\n\t\t- [ブランチ名を変更](#%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E5%90%8D%E3%82%92%E5%A4%89%E6%9B%B4)\n\t\t- [NOTE: GitHubでmasterを](#note-github%E3%81%A7master%E3%82%92)\n\t\t- [ブランチを削除](#%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%82%92%E5%89%8A%E9%99%A4)\n\t\t- [リモートブランチの削除](#%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%AE%E5%89%8A%E9%99%A4)\n\t- [git status](#git-status)\n\t- [git add](#git-add)\n\t\t- [git add 取り消し](#git-add-%E5%8F%96%E3%82%8A%E6%B6%88%E3%81%97)\n\t- [git commit](#git-commit)\n\t\t- [Add Signed-off-by message](#add-signed-off-by-message)\n\t- [git log](#git-log)\n\t- [git push](#git-push)\n- [merge and rebaseの理解](#merge-and-rebase%E3%81%AE%E7%90%86%E8%A7%A3)\n\t- [merge and rebaseの基本](#merge-and-rebase%E3%81%AE%E5%9F%BA%E6%9C%AC)\n\t- [補足 merge: fast-forward ffと non fast-forwardno-ffの違い](#%E8%A3%9C%E8%B6%B3-merge-fast-forward-ff%E3%81%A8-non-fast-forwardno-ff%E3%81%AE%E9%81%95%E3%81%84)\n\t- [テストデータ準備](#%E3%83%86%E3%82%B9%E3%83%88%E3%83%87%E3%83%BC%E3%82%BF%E6%BA%96%E5%82%99)\n\t- [mergeしてみるconflictあり](#merge%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8Bconflict%E3%81%82%E3%82%8A)\n\t- [rebaseしてみるconflictあり](#rebase%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8Bconflict%E3%81%82%E3%82%8A)\n\t- [補足 conflict解消のための取り込みパターン](#%E8%A3%9C%E8%B6%B3-conflict%E8%A7%A3%E6%B6%88%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E5%8F%96%E3%82%8A%E8%BE%BC%E3%81%BF%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3)\n- [Conflict解消](#conflict%E8%A7%A3%E6%B6%88)\n\t- [ベースブランチの最新を取り込む merge](#%E3%83%99%E3%83%BC%E3%82%B9%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%AE%E6%9C%80%E6%96%B0%E3%82%92%E5%8F%96%E3%82%8A%E8%BE%BC%E3%82%80-merge)\n\t- [ベースブランチの最新を取り込む rebase](#%E3%83%99%E3%83%BC%E3%82%B9%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%AE%E6%9C%80%E6%96%B0%E3%82%92%E5%8F%96%E3%82%8A%E8%BE%BC%E3%82%80-rebase)\n- [Undo and Change Commit](#undo-and-change-commit)\n\t- [commitを打ち消しの基本](#commit%E3%82%92%E6%89%93%E3%81%A1%E6%B6%88%E3%81%97%E3%81%AE%E5%9F%BA%E6%9C%AC)\n\t- [テストデータを準備する](#%E3%83%86%E3%82%B9%E3%83%88%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E6%BA%96%E5%82%99%E3%81%99%E3%82%8B)\n\t- [commitを打ち消す](#commit%E3%82%92%E6%89%93%E3%81%A1%E6%B6%88%E3%81%99)\n\t- [commit logを書き換える](#commit-log%E3%82%92%E6%9B%B8%E3%81%8D%E6%8F%9B%E3%81%88%E3%82%8B)\n- [Update Commit Message](#update-commit-message)\n\t- [直前のCommitメッセージを修正](#%E7%9B%B4%E5%89%8D%E3%81%AEcommit%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%82%92%E4%BF%AE%E6%AD%A3)\n\t- [つ前のCommitメッセージを修正](#%E3%81%A4%E5%89%8D%E3%81%AEcommit%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%82%92%E4%BF%AE%E6%AD%A3)\n- [Squash merge](#squash-merge)\n\t- [Squash mergeの基本](#squash-merge%E3%81%AE%E5%9F%BA%E6%9C%AC)\n\t- [テストデータを準備する](#%E3%83%86%E3%82%B9%E3%83%88%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E6%BA%96%E5%82%99%E3%81%99%E3%82%8B)\n\t- [squash mergeする](#squash-merge%E3%81%99%E3%82%8B)\n\t- [ただのmerge fast-forward merge](#%E3%81%9F%E3%81%A0%E3%81%AEmerge-fast-forward-merge)\n\t- [PRをSquash mergeする](#pr%E3%82%92squash-merge%E3%81%99%E3%82%8B)\n- [Undo/取り消しパターンrevert, reset, merge --abort,etc](#undo%E5%8F%96%E3%82%8A%E6%B6%88%E3%81%97%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3revert-reset-merge---abortetc)\n\t- [Undoの基本](#undo%E3%81%AE%E5%9F%BA%E6%9C%AC)\n\t\t- [git merge --abort](#git-merge---abort)\n\t\t- [git reset commitID](#git-reset-commitid)\n\t\t- [git revert commitID](#git-revert-commitid)\n\t- [テスト準備](#%E3%83%86%E3%82%B9%E3%83%88%E6%BA%96%E5%82%99)\n\t- [Undoテスト1: マージ成功後に元に戻すgit reset](#undo%E3%83%86%E3%82%B9%E3%83%881-%E3%83%9E%E3%83%BC%E3%82%B8%E6%88%90%E5%8A%9F%E5%BE%8C%E3%81%AB%E5%85%83%E3%81%AB%E6%88%BB%E3%81%99git-reset)\n\t- [Undoテスト2: マージ成功後に元に戻すgit revert](#undo%E3%83%86%E3%82%B9%E3%83%882-%E3%83%9E%E3%83%BC%E3%82%B8%E6%88%90%E5%8A%9F%E5%BE%8C%E3%81%AB%E5%85%83%E3%81%AB%E6%88%BB%E3%81%99git-revert)\n\t- [Undoテスト3: コンフリクトでマージ失敗マージ未完了git merge --abort](#undo%E3%83%86%E3%82%B9%E3%83%883-%E3%82%B3%E3%83%B3%E3%83%95%E3%83%AA%E3%82%AF%E3%83%88%E3%81%A7%E3%83%9E%E3%83%BC%E3%82%B8%E5%A4%B1%E6%95%97%E3%83%9E%E3%83%BC%E3%82%B8%E6%9C%AA%E5%AE%8C%E4%BA%86git-merge---abort)\n\t- [Undoテスト4: コンフリクトでマージ失敗（マージ未完了）git reset](#undo%E3%83%86%E3%82%B9%E3%83%884-%E3%82%B3%E3%83%B3%E3%83%95%E3%83%AA%E3%82%AF%E3%83%88%E3%81%A7%E3%83%9E%E3%83%BC%E3%82%B8%E5%A4%B1%E6%95%97%E3%83%9E%E3%83%BC%E3%82%B8%E6%9C%AA%E5%AE%8C%E4%BA%86git-reset)\n- [cherry-pick](#cherry-pick)\n\t- [cherry-pickの基本](#cherry-pick%E3%81%AE%E5%9F%BA%E6%9C%AC)\n\t- [絵で比較するmerge vs cherry-pick](#%E7%B5%B5%E3%81%A7%E6%AF%94%E8%BC%83%E3%81%99%E3%82%8Bmerge-vs-cherry-pick)\n\t- [git merge commit2](#git-merge-commit2)\n\t- [git cherry-pick commit4](#git-cherry-pick-commit4)\n\t- [git cherry-pick commit5 commit6 commit7](#git-cherry-pick-commit5-commit6-commit7)\n\t- [テスト準備](#%E3%83%86%E3%82%B9%E3%83%88%E6%BA%96%E5%82%99)\n\t- [git mergeテスト cherry-pickとの動きの比較のための実施](#git-merge%E3%83%86%E3%82%B9%E3%83%88-cherry-pick%E3%81%A8%E3%81%AE%E5%8B%95%E3%81%8D%E3%81%AE%E6%AF%94%E8%BC%83%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E5%AE%9F%E6%96%BD)\n\t- [git cherry-pick テスト](#git-cherry-pick-%E3%83%86%E3%82%B9%E3%83%88)\n\t- [GitHubで演習](#github%E3%81%A7%E6%BC%94%E7%BF%92)\n- [PRレビュー](#pr%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC)\n\t- [リモートブランチをfetchしてレビュー1 remote-add + fetch](#%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%82%92fetch%E3%81%97%E3%81%A6%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC1-remote-add--fetch)\n\t- [リモートBranchをfetchしてレビュー2 PR#とブランチ名でfetch](#%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88branch%E3%82%92fetch%E3%81%97%E3%81%A6%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC2-pr%E3%81%A8%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E5%90%8D%E3%81%A7fetch)\n- [Subtree](#subtree)\n\t- [add subtree](#add-subtree)\n\t- [pull subtree](#pull-subtree)\n- [Tag](#tag)\n\t- [add tag](#add-tag)\n\t- [check tags](#check-tags)\n\t- [delete tag](#delete-tag)\n- [Stash](#stash)\n\t- [変更待避 stashしてstash一覧表示](#%E5%A4%89%E6%9B%B4%E5%BE%85%E9%81%BF-stash%E3%81%97%E3%81%A6stash%E4%B8%80%E8%A6%A7%E8%A1%A8%E7%A4%BA)\n\t- [stashした内容を復元](#stash%E3%81%97%E3%81%9F%E5%86%85%E5%AE%B9%E3%82%92%E5%BE%A9%E5%85%83)\n\t- [stashした内容を削除](#stash%E3%81%97%E3%81%9F%E5%86%85%E5%AE%B9%E3%82%92%E5%89%8A%E9%99%A4)\n\t- [rebase時のstash対応](#rebase%E6%99%82%E3%81%AEstash%E5%AF%BE%E5%BF%9C)\n- [APPENDIX](#appendix)\n\t- [GitHub CLI](#github-cli)\n\t- [GitHubでmasterブランチをmainに変更](#github%E3%81%A7master%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%82%92main%E3%81%AB%E5%A4%89%E6%9B%B4)\n\n\u003c!-- /TOC --\u003e\n\nThis is my personal GitHub sandbox repository, and its content is primarily based on past GitHub trainings I've done for GitHub newbies.\n\n## Git コンセプト\n\nGitはスナップショットの集合であり、差分ではない\n  - Git: データは一連のスナップショット\n  - CVS、Subversion、Perforce、Bazaar: 差分リスト\n\nGitの基本ワークフロー\n  1. 作業ディレクトリのファイルを修正する\n  2. 修正されたファイル(`modified`)のスナップショットをステージング・エリアに追加(`git add`)\n  3. コミットする(`git commit`)\n\nGitプロジェクトの3つの主要な部分\n- `Working Directory (Working Tree)`: プロジェクトの1つのバージョンがチェックアウトされたもの。Gitディレクトリの圧縮されたデータベースから引き出されてディスクに配置。自分たちが直接編集するのはここ。\n- `Staging Area (stage / index / cache)`: 次のコミットに何が含まれるかに関しての情報を蓄えた1つのファイル。「インデックス」とも呼ばれる。実体は`.git/index`\n- `Local Repository (.git)`: プロジェクトのメタデータとオブジェクトのデータベース。リポジトリをクローンしたときにコピーされる。HEAD\n\n![](assets/git-storage-model.png)\n\nref: https://www3.ntu.edu.sg/home/ehchua/programming/howto/Git_HowTo.html\n\nHEAD / Stage(index) / Working directory\n\n-  `HEAD`: the last commit in the currently checked-out branch\n-  `Stage(index)`: Staging area, stage, index, cacheはすべて同じ\n-  `working directory (working tree)`\n\n![](https://i.stack.imgur.com/y8gFk.png)\n\nref: [How do I show the changes which have been staged?](https://stackoverflow.com/questions/1587846/how-do-i-show-the-changes-which-have-been-staged)\n\nファイルの3つのステータス\n  - `Commited` コミット済: ローカル・データベースにデータが安全に格納されていること\n  - `Modified` 修正済 \n  - `Staged` ステージ済: 現在のバージョンの修正されたファイルに印をつけている状態\n\n追跡されているとは？= 直近のスナップショットに存在していること\n- `untracked`: 追跡されてない\n- `tracked`: 追跡されている\n  - `unmodified`: 修正されていない\n  - `modified`: 修正済み\n  - `staged`: ステージ済み = ステージングエリアにも存在する\n\nlocal / origin / upstreamの概念\n\n- `upstream`: original repo. もしForkしているならば、Fork元のrepoがupstream\n- `origin`:  your own repo on GitHub\n\n![](https://i.stack.imgur.com/cEJjT.png)\n\nref: [What is the difference between origin and upstream on GitHub?](https://stackoverflow.com/questions/9257533/what-is-the-difference-between-origin-and-upstream-on-github)\n\n\n参照ページ\n- [Gitの基本 - 1.3 使い始める](https://git-scm.com/book/ja/v2/%E4%BD%BF%E3%81%84%E5%A7%8B%E3%82%81%E3%82%8B-Git%E3%81%AE%E5%9F%BA%E6%9C%AC)\n- [Gitの基本 - 変更内容のリポジトリへの記録](https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E5%9F%BA%E6%9C%AC-%E5%A4%89%E6%9B%B4%E5%86%85%E5%AE%B9%E3%81%AE%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%B8%E3%81%AE%E8%A8%98%E9%8C%B2)\n- [How do I show the changes which have been staged?](https://stackoverflow.com/questions/1587846/how-do-i-show-the-changes-which-have-been-staged)\n- [What is the difference between origin and upstream on GitHub?](https://stackoverflow.com/questions/9257533/what-is-the-difference-between-origin-and-upstream-on-github)\n\n\nGitの内部構造 (ここでは扱わない)\n- [Gitの内側 - Gitオブジェクト](http://git-scm.com/book/ja/v2/Git%E3%81%AE%E5%86%85%E5%81%B4-Git%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88)\n- [Gitの内側 - Gitの参照](http://git-scm.com/book/ja/v2/Git%E3%81%AE%E5%86%85%E5%81%B4-Git%E3%81%AE%E5%8F%82%E7%85%A7)\n- [Gitのインデックスの中身](https://zenn.dev/kaityo256/articles/inside_the_index)\n\n## GitHubリポジトリ設定\n\n0 Pre-Requisites\n\n- GitHub Account\n- [テスト用 Repo](https://github.com/yokawasa/monorepo-sandbox)への Collaborator権限（Collaborator出ない場合はForkからのPRマージ）\n\n1 `main`ブランチのマージを レビューを必須にする\n\n![](assets/branch-setup.png)\n\n2 管理者も対象 (`main`ブランチのマージを PRレビュー必須) \n\n`Include administrators` にチェックを入れる\n\n![](assets/branch-setup-include-admin.png)\n\nref: [ブランチ保護ルール](https://docs.github.com/ja/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule)\n\n\n## Git 初期設定\n\n### git config\n\nローカルリポジトリ用のユーザー情報設定を行う\n\n設定内容の確認\n\n```bash\ngit config -l\n\nuser.name=yokawasa\nuser.email=yokawasa@gmail.com\n...\n```\n\n`user.name`と`user.address`を設定する。`--global`オプションでglobalレベルの設定であることを指定。一方、`--local`でリポジトリレベルの設定が可能。\n\n```bash\n#  git config --global user.name \"[name]\"\ngit config --global user.name \"Yoichi Kawasaki\"\n\n# git config --global user.email \"[email address]\"\ngit config --global user.name \"yokawasa@gmail.com\"\n```\n\n再び、設定を確認\n\n```bash\ngit config -l\n\nuser.name=Yoichi Kawasaki\nuser.email=yokawasa@gmail.com\n```\n\nなお、この設定は `~/.gitconfig`に保存される\n\n```bash\n cat ~/.gitconfig\n\n...\n[user]\n  name = Yoichi Kawasaki\n  email = yokawasa@gmail.com\n```\n\nその他git config設定については\n- [Attlassian Gitチュートリアル git config](https://www.atlassian.com/ja/git/tutorials/setting-up-a-repository/git-config)\n\n### git alias\n\nGitエイリアスの設定。checkoutにたいしてco、commitに対してciのエイリアスを作成する\n\n```\ngit config --global alias.co checkout\ngit config --global alias.ci commit\n```\n\nなお、この設定は `~/.gitconfig`に保存される\n\n```bash\n cat ~/.gitconfig\n\n...\n[alias]\n  co = checkout\n  ci = commit\n```\n\n作成したエイリアスco (=checkout)を使う\n\n```\n# hogeブランチにスイッチ\ngit co hoge\n```\n\nその他git alias設定については\n- [Attlassian Gitチュートリアル git config](https://www.atlassian.com/ja/git/tutorials/setting-up-a-repository/git-config)\n\n\n\u003e Note: git sandboxで使用するgit config, alias設定\n\u003e ```\n\u003e # ff merge false\n\u003e git config --global --add merge.ff false\n\u003e # ff merge in pull\n\u003e git config --global --add pull.ff only\n\u003e \n\u003e # git log graph pretty format表示\n\u003e git config --global alias.l \"log --graph --all --pretty=format:'%C(yellow)%h%C(cyan)%d%Creset %s %C(white)- %an, %ar%Creset'\"\n\u003e \n\u003e ```\n\n## プルリクエスト経由でリモートmainにマージ\n\n\u003e **NOTE**\n\u003e - mainへの直push絶対にやらない  (一般的にはブランチ保護ルールを適用してmain直pushをブロックする)\n\u003e - 作業用ブランチを切って作業する\n### git clone \n\nテスト用リポジトリをgit cloneしてディレクトリを移動\n\n```\ngit clone git@github.com:yokawasa/monorepo-sandbox.git\ncd monorepo-sandbox\n```\n\n### git branch\n\n#### ブランチ作成\n\n作業用ブランチを作成\n\n```\n# git checkout -b \u003c作成する作業用ブランチ\u003e\ngit checkout -b my-branch1\n```\n\n#### ブランチ一覧表示\n\nブランチ一覧を表示。今がmy-branch1にいることがわかる\n\n```\ngit branch\n\n  main\n* my-branch1\n```\n\n#### あるブランチに移動\n\nmainブランチに移動\n\n```\n# git checkout \u003cbranch名\u003e\ngit checkout main\n```\n\n#### ブランチ名を変更\n\nmy-branch1ブランチの名前をmy-branch1-aに変更（rename）\n\n```\n# git branch -m \u003cnew-branch-name\u003e\n# Use the -m flag to change the name of the branch\n\ngit branch -m my-branch1-a\n```\n\n#### NOTE: GitHubでmasterを\n\n#### ブランチを削除\n\nmy-branch1-aブランチを削除\n\n```\n# git branch -d \u003cbranch名\u003e\ngit branch -d my-branch1-a\n```\n\nブランチ一覧を表示。my-branch1-aが消えていることを確認\n\n```\ngit branch \n*  main\n```\n\n最後に、再び作業用ブランチmy-branch2を作成する\n\n```bash\ngit checkout -b my-branch2\n```\n\n#### リモートブランチの削除\n\n```\ngit push --delete origin \u003cbranch_name\u003e\n# もしくは 削除対象ブランチの先頭に「:」をつける\n# 例 masterを削除) git push origin :master\ngit push origin :\u003cbranch_name\u003e\n```\nref: https://qiita.com/yuu_ta/items/519ea47ac2c1ded032d9\n\n\n### git status\n\n`git status`はstaged, unstaged, untrackedな状態のファイルを一覧表示するコマンド。\n\nまずは、tools/service/svc-a配下にtest.shファイルを作成する。\n\n```\ncp -p tools/service/svc-a/svc-a.sh tools/service/svc-a/test.sh \n```\n\n次に、`git status`でGitファイルの状態を確認する。test.shが`Untracked`であることがわかる\n\n```\ngit status\n\nOn branch my-branch2\nUntracked files:\n  (use \"git add \u003cfile\u003e...\" to include in what will be committed)\n        tools/service/svc-a/test.sh\n\nnothing added to commit but untracked files present (use \"git add\" to track)\n```\n\n### git add\n\n`git add`は変更されたファイルをステージエリア（インデックス）に追加する。\nさきほど追加されたtest.shをステージエリア（インデックス）に追加する。\n\n```bash\ngit add tools/service/svc-a/test.sh \n```\n\n`git status`でファイルの状態を確認する。test.shがステージエリアにある（= Changes to be committed）ことがわかる。\n\n```\ngit status\n\nOn branch my-branch2\nChanges to be committed:\n  (use \"git restore --staged \u003cfile\u003e...\" to unstage)\n        new file:   tools/service/svc-a/test.sh\n```\n\n#### git add 取り消し\n\nステージエリア（インデックス）に追加したファイルを取り消したい場合\n\n```bash\ngit rm --cached \u003cfilename\u003e\n```\n\n### git commit\n\n`git commit`でァイルをCommitedステータスに変更。`-m`オプションで追加メッセージを指定可能。`-m`ない場合はeditが立ち上がり、メッセージの入力が可能\n\n```bash\ngit commit -m \"updated\"\n```\n\n#### Add Signed-off-by message\n\nよくOSSでsign-off-byをつけたメッセージが求められるプロジェクトがある。\nたとえばこちらのプロジェクト → [Developer Certificate of Origin in KEDA](https://github.com/kedacore/keda/blob/main/CONTRIBUTING.md#developer-certificate-of-origin-signing-your-work)\n\n`git commit`に`-s` | `--signoff`オプションを追加することでcommitメッセージにsign-off-byを付与できる。\n\n```\ngit commit -s -m 'This is my commit message'\n\ngit log\n\nAuthor: Yoichi Kawasaki \u003cyokawasa@gmail.com\u003e\nDate:   Thu Jun 2 22:43:23 2022 +0900\n\n    This is my commit message\n    \n    Signed-off-by: Yoichi Kawasaki \u003cyokawasa@gmail.com\u003e \u003c\u003c\u003c\u003c\u003c\u003c これ\n```\n\nなお、sign-off-byメッセージは通常メッセージと同じように`--amend`オプションで修正することが可能\n\n```\ngit commit --amend -s\n```\n\nデフォルトでコミットメッセージにsign-offを付与する方法ついてはこちらの[議論](https://stackoverflow.com/questions/15015894/git-add-signed-off-by-line-using-format-signoff-not-working)が参考になる。\n\nまた、commit message templateを利用してももよいかもしれない。\n\n```\nSigned-off-by: Your Name \u003cyour.email@example.com\u003e\n```\n\nこれを次のようにcommit templateとして設定する\n\n```\ngit config --global commit.template ~/MYPROJECT/git-template\n```\n### git log\n\nGitのログの履歴を確認する\n\n```\ngit log\n\ncommit c835e6bd662005d96467ac60a3312a725796248f (HEAD -\u003e my-branch2, main)\nAuthor: Yoichi Kawasaki \u003cyokawasa@gmail.com\u003e\nDate:   Tue Jun 7 13:39:50 2022 +0900\n\n    remove space\n\ncommit 5c11f7c1187d7d53749dd91b4d3eb7bfca38d020 (origin/main, origin/HEAD)\nAuthor: Yoichi Kawasaki \u003cyokawasa@gmail.com\u003e\nDate:   Tue Jun 7 13:37:10 2022 +0900\n\n    add space\n\ncommit be9518e5377500cb3f1424df69a90ad959e7e98b\nMerge: a8cd49a 02791c2\nAuthor: Yoichi Kawasaki \u003cyokawasa@gmail.com\u003e\nDate:   Tue Jun 7 12:59:02 2022 +0900\n\n    Merge pull request #1 from yokawasa/init-entry\n    \n    add initial files\n```\n\n### git push\n\nremoteリポジトリにpush\n\n## merge and rebaseの理解\n\n### merge and rebaseの基本\n\nmergeもrebaseも目的は１つ: 変更を１つのブランチから別のブランチに統合。ただしアプローチが異なる\n\n最初の状態\n\n![](assets/mrege-rebase-basic-before.png)\n\nmergeは？\n- 変更を１つのブランチから別のブランチに統合。分岐したブランチのコミットをとってこない\n- fast-forwardとnon-fast-forwardによりmergeコミットが生成を区別\n  - fast-forward merge(--ff): マージコミットは作られず、ブランチの参照先の更新だけが更新される\n  - non fast-forward merge (--no-ff) マージ : 意図的にfast-forwardを行わないコミット。マージコミットが作られる  \n\n```\ngit merge \u003ccommit/branch\u003e\ngit merge --ff \u003cbranch\u003e\ngit merge --no-ff \u003cbranch\u003e\ngit merge \u003cbranch\u003e -m \"コミットメッセージの内容\"\n```\n\nmerge後の状態\n\n![](assets/mrege-rebase-basic-after-merge.png)\n\nrebaseは?\n- コミット履歴を移動したり修正、削除したりするコマンド\n- マージ前にコミット履歴をきれいにする目的で使用される事が多い (git rebaseしてからPR出す)\n- 分岐した時点からのコミット内容をとってきて、自分の変更後のコミットをその先端に移動する。取得してきたコミット番号は変わらないが、自分のブランチのコミットは変更される（過去のコミット履歴が変わるため）\n\n```\ngit rebase \u003cbase\u003e   # base = commit, branch, tag, etc.\n```\n\nrebase後の状態\n\n![](assets/mrege-rebase-basic-after-rebase.png)\n\nref: https://www.atlassian.com/git/tutorials/merging-vs-rebasing\n\n### 補足 merge: fast-forward (ff)と non fast-forward(no-ff)の違い\n\n- fast-forwardマージ (--ff): マージコミットは作られず、ブランチの参照先の更新だけが更新される\n- non fast-forwardマージ (--no-ff) マージ : 意図的にfast-forwardを行わないコミット。マージコミットが作られる  \n\nmerge commitがあると以下の点で便利。\n- merge commitのdiffを見るだけでそのブランチで行われた作業を見るのが容易\n- merge commitを取り消すことでmerge作業自体をなかったことにしたい場合も簡単\n\n逆にmerge commitが作られないと、 mainがその後更新されていった場合にfeatureブランチで行われた作業を参照するのが面倒になる。また、mergeの取り消しを行いたいと思った場合にもかなり不便。よって、no-ffでmergeするのがよい。強制的にmergeでno-ffにするならば、次の設定をいれるとよい。\n\n```\ngit config --global --add merge.ff false\n```\n\n[注意] ただしpullを行った時に行われるmergeにも--no-ffが有効になるため、pullを行う度にmergeコミットが発行されてコミットログが荒れる。なので、pullのときは除外したい。その場合は次の設定をいれるとよい。\n\n```\ngit config --global --add pull.ff only\n```\n\nまとめると、次の設定をいれておくとよい\n```\ngit config --global --add merge.ff false\ngit config --global --add pull.ff only\n```\n\nref: \n- [gitのmerge --no-ff のススメ](https://qiita.com/nog/items/c79469afbf3e632f10a1)\n- [A successful Git branching model (日本語訳)](http://keijinsonyaban.blogspot.com/2010/10/a-successful-git-branching-model.html)\n\n### テストデータ準備\n\n```\ngit checkout main\ntouch test.md\necho \"add c0\" \u003e\u003e test.md \u0026\u0026 git add test.md \u0026\u0026 git commit -m \"c0\"\necho \"add c1\" \u003e\u003e test.md \u0026\u0026 git add test.md \u0026\u0026 git commit -m \"c1\"\necho \"add c2\" \u003e\u003e test.md \u0026\u0026 git add test.md \u0026\u0026 git commit -m \"c2\"\n\ngit checkout -b myfeature\necho \"add c3\" \u003e\u003e test.md \u0026\u0026 git add test.md \u0026\u0026 git commit -m \"c3\"\necho \"add c4\" \u003e\u003e test.md \u0026\u0026 git add test.md \u0026\u0026 git commit -m \"c4\"\n\ngit checkout main\necho \"add c5\" \u003e\u003e test.md \u0026\u0026 git add test.md \u0026\u0026 git commit -m \"c5\"\n```\n\n### mergeしてみる(conflictあり)\n\nconflictありmergeの場合は、fast-forward or not fast-forward どちらでもmerge commitが作られる。\n\nmyfeatureブランチに移動して、mainブランチをmergeする\n\n```bash\n# myfeatureブランチに移動\ngit checkout myfeature\n\n# git log表示\ngit l\n\n* bb5ca52 (main) c5 - Yoichi Kawasaki, 8 minutes ago\n| * 49fd048 (HEAD -\u003e myfeature) c4 - Yoichi Kawasaki, 9 minutes ago\n| * 9bc41fb c3 - Yoichi Kawasaki, 10 minutes ago\n|/  \n* 623ce75 c2 - Yoichi Kawasaki, 11 minutes ago\n* 43c5fd6 c1 - Yoichi Kawasaki, 11 minutes ago\n* 7cb76e3 c0 - Yoichi Kawasaki, 12 minutes ago\n\n# mainブランチをmergeする\ngit merge main\n\n# 下記のようなConflictメッセージが出力される\nAuto-merging test.md\nCONFLICT (content): Merge conflict in test.md\nAutomatic merge failed; fix conflicts and then commit the result.\n\n# 手動でConflictを解消してtest.mdをcommitする\nvi test.md\ngit add test.md\ngit commit -m \"fix conflict\"\n\n# merge後のgit log表示\ngit l\n\n*   d22507e (HEAD -\u003e myfeature) fix conflict - Yoichi Kawasaki, 3 seconds ago\n|\\  \n| * bb5ca52 (main) c5 - Yoichi Kawasaki, 6 minutes ago\n* | 49fd048 c4 - Yoichi Kawasaki, 7 minutes ago\n* | 9bc41fb c3 - Yoichi Kawasaki, 7 minutes ago\n|/  \n* 623ce75 c2 - Yoichi Kawasaki, 8 minutes ago\n* 43c5fd6 c1 - Yoichi Kawasaki, 9 minutes ago\n* 7cb76e3 c0 - Yoichi Kawasaki, 9 minutes ago\n```\n\n最後に、次の処理のために今回のmerge commitをなかったコトにする\n```\n# 直前のコミットを取り消しする\ngit reset --hard HEAD^\n```\n\n### rebaseしてみる(conflictあり)\n\nmyfeatureブランチに移動して、mainブランチをrebaseする\n\n```bash\n# myfeatureブランチに移動\ngit checkout myfeature\n\n# git log表示\ngit l\n\n# mainブランチをrebaseする\ngit rebase main\n\n# conflict発生\nFirst, rewinding head to replay your work on top of it...\nApplying: c3\nUsing index info to reconstruct a base tree...\nM       test.md\nFalling back to patching base and 3-way merge...\nAuto-merging test.md\nCONFLICT (content): Merge conflict in test.md\nerror: Failed to merge in the changes.\nPatch failed at 0001 c3\nhint: Use 'git am --show-current-patch' to see the failed patch\nResolve all conflicts manually, mark them as resolved with\n\"git add/rm \u003cconflicted_files\u003e\", then run \"git rebase --continue\".\nYou can instead skip this commit: run \"git rebase --skip\".\nTo abort and get back to the state before \"git rebase\", run \"git rebase --abort\".\n\n# 手動でconflictを修復して git add して git rebase --continueする。これをauto-mergeが成功するまでやる\nvi test.md\ngit add test.md\ngit rebase --continue\n\n# rebase後のgit log表示\ngit l\n\n* 68ef496 (HEAD -\u003e myfeature) c4 - Yoichi Kawasaki, 13 minutes ago\n* e90fd40 c3 - Yoichi Kawasaki, 14 minutes ago\n* bb5ca52 (main) c5 - Yoichi Kawasaki, 12 minutes ago\n* 623ce75 c2 - Yoichi Kawasaki, 15 minutes ago\n* 43c5fd6 c1 - Yoichi Kawasaki, 15 minutes ago\n* 7cb76e3 c0 - Yoichi Kawasaki, 16 minutes ago\n```\n\n\n### 補足 conflict解消のための取り込みパターン\n\n`=======`より上がHEAD (Current Change)、下が取り込む変更 (Incoming Change)。\n\n![](assets/resolve-conflict.png)\n\nVS Codeの場合、以下の３つのオプションから取り込み方を選択できる機能あり\n- Accept Current Change\n- Accept Incoming Change\n- Accept Both Change\n\n\n\n## Conflict解消\n\nベースブランチを pull またはfetchして、ターゲットブランチでmerge または rebaseする。 For merge and rebase, see: [merge and rebaseの理解](#merge-and-rebaseの理解)\n\n\n### ベースブランチの最新を取り込む (merge)\n\nmyfeatureブランチにベースブランチ(main) の最新状態を取り込む\n\n```sh\ngit pull origin main\n# or git fetch origin main\n\ngit co myfeature\ngit merge main\n```\n\nもしmerge中にコンフリクトが発生した場合、Gitはエラーを出力し、問題のあるファイルを表示する。対処法は下記パートを参照せよ\n\n- [merge and rebaseの理解/mergeしてみるconflictあり](#mergeしてみるconflictあり)\n\n\n### ベースブランチの最新を取り込む (rebase)\n\nmyfeatureブランチにベースブランチ(main) の最新状態を取り込む\n\n```sh\ngit pull origin main\n# or git fetch origin main\n\ngit co myfeature\n\n# myfeatureブランチをmainにリベース。これにより、mainの変更を取り込むことができる\ngit rebase origin/main\n```\n\nもしリベース中にコンフリクトが発生した場合、Gitはエラーを出力し、問題のあるファイルを表示する。対処法は下記パートを参照せよ\n\n- [merge and rebaseの理解/rebaseしてみる(conflictあり)\n](#mergeしてみるconflictあり)\n\nリベースが成功したら、ローカルの変更をリモートにプッシュする。このとき、--forceフラグが必要になる\n\n```sh\ngit push origin myfeature --force\n```\n\n\n\n## Undo and Change Commit\n\n### commitを打ち消しの基本\n\ngit revert に打ち消したい`commit-id`を指定する\n\n```\n# コミット打ち消し ＋「Revert + \u003c元のコミットのメッセージ\u003e」なコミット作成\ngit revert  \u003ccommit-id\u003e\n\n# コミット打ち消し ＋「任意のメッセージ」なコミット作成\ngit revert -e \u003ccommit-id\u003e\n\n# コミット打ち消し（コミットは作成しない）\ngit revert  -n \u003ccommit-id\u003e\n\n# マージコミットをうち消し (-m オプションなしでマージコミットをrevertするとエラーが出る)\ngit revert -m \u003cparent-number\u003e  \u003ccommit-id\u003e\n# parent-number = 1 (1つ目の親) or 2 (2つ目の親)\n# git show \u003ccommit-id\u003eで下記のような結果が表示された場合, eaa9618 -\u003e 1, cddcef9-\u003e2となる\n# git show \u003ccommit-id\u003e\n# ---\n# git show 9c8582d\n#   commit 9c8582de1c2446a29b7f451d00eff0f71c0ebc3d (HEAD -\u003e merge-branch, origin/merge-branch)\n#.  Merge: eaa9618 cddcef9\n# ---\n```\n\n### テストデータを準備する\n\n次のようにrevert-testブランチに移動してテストコミットをする\n\n```\ngit checkout -b revert-test\n\ntouch revert.md\n\necho \"add c0\" \u003e\u003e revert.md \u0026\u0026 git add revert.md \u0026\u0026 git commit -m \"c0\"\necho \"add c1\" \u003e\u003e revert.md \u0026\u0026 git add revert.md \u0026\u0026 git commit -m \"c1\"\necho \"add c2\" \u003e\u003e revert.md \u0026\u0026 git add revert.md \u0026\u0026 git commit -m \"c2\"\necho \"add c3\" \u003e\u003e revert.md \u0026\u0026 git add revert.md \u0026\u0026 git commit -m \"c3\"\n```\n\n### commitを打ち消す\n\nファイル内容を確認\n\n```\ncat revert.md\n\nadd c0\nadd c1\nadd c2\nadd c3\n```\n\nコミットログを確認\n```\ngit l\n\n* 3dd91e1 (HEAD -\u003e revert-test) c3 - Yoichi Kawasaki, 54 seconds ago\n* 0cf6f21 c2 - Yoichi Kawasaki, 57 seconds ago\n* 7223760 c1 - Yoichi Kawasaki, 61 seconds ago\n* 9591f87 c0 - Yoichi Kawasaki, 66 seconds ago\n```\n\nここでc3 (commit id: `3dd91e1` )のコミットを打ち消す\n\n```\ngit revert -e 3dd91e1\n```\n\nコミットメッセージを作成後、ファイル内容とログを確認。c3のコミットが打ち消されていることがわかる\n\n```\ncat revert.md\n\nadd c0\nadd c1\nadd c2\n\ngit l \n\n* 9150f70 (HEAD -\u003e revert-test) Revert \"c3\" - Yoichi Kawasaki, 2 minutes ago\n* 3dd91e1 c3 - Yoichi Kawasaki, 7 minutes ago\n* 0cf6f21 c2 - Yoichi Kawasaki, 7 minutes ago\n* 7223760 c1 - Yoichi Kawasaki, 7 minutes ago\n* 9591f87 c0 - Yoichi Kawasaki, 7 minutes ago\n```\n \n次に、さらにrevert commit (`9150f70`) をrevertしてみる\n\n```\ngit revert 9150f70\n```\n\nコミットメッセージを作成後、ファイル内容とログを確認。c3の打ち消しこみっとが打ち消されていることがわかる\n```\ncat revert.md\n\nadd c0\nadd c1\nadd c2\nadd c3\n\ngit l\n\n* 124421f (HEAD -\u003e revert-test) Revert \"Revert \"c3\"\" - Yoichi Kawasaki, 86 seconds ago\n* 9150f70 Revert \"c3\" - Yoichi Kawasaki, 5 minutes ago\n* 3dd91e1 c3 - Yoichi Kawasaki, 10 minutes ago\n* 0cf6f21 c2 - Yoichi Kawasaki, 10 minutes ago\n* 7223760 c1 - Yoichi Kawasaki, 10 minutes ago\n* 9591f87 c0 - Yoichi Kawasaki, 10 minutes ago\n```\n\n### commit logを書き換える\n\n```\ngit rebase -i \u003c書き換えたい1つ前のcommit id\u003e\n\ncommand の内容\n----------------------------------------------------------------\n# Commands:\n# p, pick \u003ccommit\u003e = use commit\n# r, reword \u003ccommit\u003e = use commit, but edit the commit message\n# e, edit \u003ccommit\u003e = use commit, but stop for amending\n# s, squash \u003ccommit\u003e = use commit, but meld into previous commit\n# f, fixup \u003ccommit\u003e = like \"squash\", but discard this commit's log message\n# x, exec \u003ccommand\u003e = run command (the rest of the line) using shell\n# b, break = stop here (continue rebase later with 'git rebase --continue')\n# d, drop \u003ccommit\u003e = remove commit\n# l, label \u003clabel\u003e = label current HEAD with a name\n# t, reset \u003clabel\u003e = reset HEAD to a label\n# m, merge [-C \u003ccommit\u003e | -c \u003ccommit\u003e] \u003clabel\u003e [# \u003coneline\u003e]\n# .       create a merge commit using the original merge commit's\n# .       message (or the oneline, if no original merge commit was\n# .       specified). Use -c \u003ccommit\u003e to reword the commit message.\n```\n\n\n\nたとえば、revertログを書き換え（ここではdrop）たい場合、`124421f`、`9150f70`より前の`3dd91e1`でrebaseする\n\n```\ngit rebase -i 3dd91e1\n```\nすると次のような編集モードでメッセージが表示される\n\n```\npick 9150f70 Revert \"c3\"\npick 124421f Revert \"Revert \"c3\"\n```\n\nこれを次のようにpickからdropに変更して保存して編集モードを終了する。\n\n```\ndrop 9150f70 Revert \"c3\"\ndrop 124421f Revert \"Revert \"c3\"\n```\n\nコミットログをみると上記2つのコミットがdropされていることが確認できる\n\n```\ngit l \n\n* 3dd91e1 (HEAD -\u003e revert-test) c3 - Yoichi Kawasaki, 16 minutes ago\n* 0cf6f21 c2 - Yoichi Kawasaki, 10 minutes ago\n* 7223760 c1 - Yoichi Kawasaki, 10 minutes ago\n* 9591f87 c0 - Yoichi Kawasaki, 10 minutes ago\n```\n\n\n## Update Commit Message\n\n### 直前のCommitメッセージを修正\n\n```bash\ngit log \n\ncommit 693b3e407553900af577e9194dd158d59eb19c81 (HEAD -\u003e main)\nAuthor: Yoichi Kawasaki \u003cyokawasa@gmail.com\u003e\nDate:   Sat Jun 4 00:15:20 2022 +0900\n\n    Wrong message \n```\n\nNo!! You can modify the latest commit message like this:\n\n```\ngit commit --amend -m \"Correct message\"\n\ncommit 693b3e407553900af577e9194dd158d59eb19c81 (HEAD -\u003e main)\nAuthor: Yoichi Kawasaki \u003cyokawasa@gmail.com\u003e\nDate:   Sat Jun 4 00:15:20 2022 +0900\n\n    Correct message \n```\n\nref: [Fix commit message](https://www.granfairs.com/blog/staff/git-commit-fix)\n\n### 3つ前のCommitメッセージを修正\n\n```\ngit log --oneline\n\nb7ec5be (HEAD -\u003e master) This is my commit message\nce12a90 This is my commit message\na046ce0 (origin/master, origin/HEAD) Added sqlcheck.yml \u003c\u003c\u003cこれを変えたい\n```\n\n↑３つ前を変えたい.\n一番新しいコミットを1として、修正したいコミットまでの数を数えて、「HEAD~」のあとにその数を入力する。 今回修正したいのは3番目なので「HEAD~3」とする\n\n```\ngit rebase -i HEAD~3\n```\n\nすると次のようなvi edit pageが表示。\n\n![](assets/update-commit-message1.png)\n\n修正したいコミット先頭の「pick」を「edit」に書き換える。\n\n![](assets/update-commit-message2.png)\n\n次のコマンドでコメントを修正する\n\n```\ngit commit --amend \n```\n\n![](assets/update-commit-message3.png)\n\nもしくは、単に`-m`オプションを付与してメッセージを更新できる\n\n```\ngit commit --amend -s -m \"Added sqlcheck.yml added message\"\n```\n\nそして、次のコマンドを入力してrebaseを成功させる。これでmainブランチにスイッチされる。\n\n```\ngit rebase --continue\n\nSuccessfully rebased and updated refs/heads/master.\n```\n\nメッセージが修正されているかを確認する\n\n```\ngit log --oneline\n\n6877420 (HEAD -\u003e master) This is my commit message\n963cc1f This is my commit message\nc49eeb0 Added sqlcheck.yml added message \u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c 期待通り変更されている\n```\n\n最後にローカルの変更をoriginにpush。このとき `--force`指定がないとpushが失敗して次のようなエラーがでる\n\n![](assets/update-commit-message4.png)\n\nこれは、rebaseをしてremote/localで異なるログを持つため、通常はそのままではgit pushできない。\n対応としては、`--force | -f`でremoteブランチをローカルのそれによって強制上書きする。\n\n```\ngit push origin master --force\n```\n\n\nref:\n- [Fix commit message](https://www.granfairs.com/blog/staff/git-commit-fix)\n- [git fast-forward mergeについて](https://qiita.com/vsanna/items/451b42f886c599a16a55)\n\n## Squash merge\n\n### Squash mergeの基本\n作業用ブランチで細かく粒度を小さくしてコミットしたログを、ある程度まとめてマージしたい場合に`--squash`オプションを活用する。\n\n```\n# ある\u003cbranch\u003eブランチの複数コミットをまとめてsquash mergeする\ngit merge --squash \u003cbranch\u003e\n```\n\n### テストデータを準備する\n\nここではsquash-testブランチから、作業用にsquash-test-devブランチを作成してそこで作業を行う（複数コミットする）。その内容をsquash-testブランチにマージするときに 複数コミットログをまとめてsquash mergeする\n\nまずはsquash-testブランチを切って、少し作業をする\n```\ngit checkout -b squash-test\n\ntouch squash.md\necho \"add c0\" \u003e\u003e squash.md \u0026\u0026 git add squash.md \u0026\u0026 git commit -m \"c0\"\necho \"add c1\" \u003e\u003e squash.md \u0026\u0026 git add squash.md \u0026\u0026 git commit -m \"c1\"\necho \"add c2\" \u003e\u003e squash.md \u0026\u0026 git add squash.md \u0026\u0026 git commit -m \"c2\"\n```\nログをみる\n```\ngit l\n\n* 7c1b5bb (squash-test) c2 - Yoichi Kawasaki, 4 minutes ago\n* 3765799 c1 - Yoichi Kawasaki, 4 minutes ago\n* 218d089 c0 - Yoichi Kawasaki, 4 minutes ago\n```\n\n次に、squash-testブランチから作業用squash-test-devブランチを切って少し作業をする\n\n```\ngit checkout -b squash-test-dev\necho \"add c3\" \u003e\u003e squash.md \u0026\u0026 git add squash.md \u0026\u0026 git commit -m \"c3\"\necho \"add c4\" \u003e\u003e squash.md \u0026\u0026 git add squash.md \u0026\u0026 git commit -m \"c4\"\necho \"add c5\" \u003e\u003e squash.md \u0026\u0026 git add squash.md \u0026\u0026 git commit -m \"c5\"\n```\nログをみる\n```\ngit l\n* 01eb340 (HEAD -\u003e squash-test-dev) c5 - Yoichi Kawasaki, 18 seconds ago\n* 3feba4b c4 - Yoichi Kawasaki, 47 seconds ago\n* f519c72 c3 - Yoichi Kawasaki, 69 seconds ago\n* 7c1b5bb (squash-test) c2 - Yoichi Kawasaki, 4 minutes ago\n* 3765799 c1 - Yoichi Kawasaki, 4 minutes ago\n* 218d089 c0 - Yoichi Kawasaki, 4 minutes ago\n```\n\n### squash mergeする\nそれではsquash-testに移動して、squash-test-devブランチの作業ログ（複数）をsquash-testブランチにsquashマージする\n\n```\n# squash-testに移動\ngit checkout squash-test\n# squash merge\ngit merge --squash squash-test-dev\n# 内容をコミットする\ngit commit -m \"merged squash-test-dev\"\n```\n\nログを見ると、複数のログがまとまったログとしてマージされていることがわかる\n\n```\ngit l\n* bf67590 (HEAD -\u003e squash-test) merged squash-test-dev - Yoichi Kawasaki, 2 seconds ago\n| * 01eb340 (squash-test-dev) c5 - Yoichi Kawasaki, 6 minutes ago\n| * 3feba4b c4 - Yoichi Kawasaki, 6 minutes ago\n| * f519c72 c3 - Yoichi Kawasaki, 7 minutes ago\n|/\n* 7c1b5bb c2 - Yoichi Kawasaki, 10 minutes ago\n* 3765799 c1 - Yoichi Kawasaki, 10 minutes ago\n* 218d089 c0 - Yoichi Kawasaki, 10 minutes ago\n```\n\n### ただのmerge (fast-forward merge)\n\nこんどは新たに作業用にsquash-test-dev2を作成して作業する\n\n```\ngit checkout -b squash-test-dev2\necho \"add c6\" \u003e\u003e squash.md \u0026\u0026 git add squash.md \u0026\u0026 git commit -m \"c6\"\necho \"add c7\" \u003e\u003e squash.md \u0026\u0026 git add squash.md \u0026\u0026 git commit -m \"c7\"\necho \"add c8\" \u003e\u003e squash.md \u0026\u0026 git add squash.md \u0026\u0026 git commit -m \"c8\"\n```\n\nそれではsquash-testに移動して、squash-test-dev2ブランチの作業ログ（複数）をsquashじゃないモードでマージする（fast-forwardマージ）。\n\n```\ngit checkout squash-test\ngit merge squash-test-dev2\n\nUpdating bf67590..6f7d160\nFast-forward\n squash.md | 3 +++\n 1 file changed, 3 insertions(+)\n```\n\nログをみると、squash-test-dev2の複数コミットログがfast-forwardマージされていることがわかる\n\n```\n* 6f7d160 (HEAD -\u003e squash-test, squash-test-dev2) c8 - Yoichi Kawasaki, 7 minutes ago\n* fdf770d c7 - Yoichi Kawasaki, 8 minutes ago\n* 061a29c c6 - Yoichi Kawasaki, 8 minutes ago\n* bf67590 merged squash-test-dev - Yoichi Kawasaki, 22 minutes ago\n| * 01eb340 (squash-test-dev) c5 - Yoichi Kawasaki, 27 minutes ago\n| * 3feba4b c4 - Yoichi Kawasaki, 28 minutes ago\n| * f519c72 c3 - Yoichi Kawasaki, 28 minutes ago\n|/\n* 7c1b5bb c2 - Yoichi Kawasaki, 31 minutes ago\n* 3765799 c1 - Yoichi Kawasaki, 31 minutes ago\n* 218d089 c0 - Yoichi Kawasaki, 31 minutes ago\n```\n\n### PRをSquash mergeする\n\nPRを作成し、approveされmergeボタンを押すときに以下のイメージのような選択肢がある。デフォルトはただのマージだけど、「Squash and merge」を選択すると、複数のコミットを１つにまとめてマージできる\n\n![](assets/squash-merge-button.png)\n\n以下 feature ブランチ→mainブランチへのPRでsquashマージしたときとそうでないときのログ履歴の違い\n\n![](assets/comparison-squash-merge-and-merge.png)\n\n\n\n## Undo/取り消しパターン(revert, reset, merge --abort,etc)\n\n### Undoの基本\n\n取り消し(Undo)はrevert, reset, merge --abortで実現可能。これらの違いについてポイントを下記する\n\n#### git merge --abort\n- ローカルマージのUndo。コンフリクト発生時などでUndo時に有効\n- **マージが完了している場合はUndoできない**\n- **コミット履歴: 残らない**\n\n#### git reset commitID\n- マージのUndo（リモートもOKだけどローカルUndoを推奨）。指定したコミットまで戻る。マージが完了していてもUndo可。\n- **コミット履歴: 消える**\n- 2つの使い方が可能\n  - 指定したコミットまで戻る: `git reset \u003ccommit\u003e`\n  - 指定したファイルのみ指定したコミットの状態に戻る:  `git reset \u003ccommit\u003e \u003cfile-path\u003e`\n- 戻す場合どこまで変更中のファイルを残すか指定する3つのオプションが指定可能: `–soft`, `–mixed`,`–hard`。基本的にさっくりと戻すことを期待していることが多いと思うので`--hard`でOK\n\n![](assets/reset-option-soft-mixed-hard.png)\n\n- 定石パターン\n  - `git reflog`との組み合わせて過去に戻る\n```bash\n#コマンド履歴の一覧を確認\ngit reflog\n#コミットを戻す\ngit reset --hard \u003ccommitID\u003e\n```\n- これを使うのはローカルのみ! 複数人での共同開発レポジトリでは使わないことを推奨\n  - コミット履歴は過去のコミットに全て紐づいているので過去のコミット履歴が変わると、その後のコミットのコミット番号も変わる。よって、git resetでコミットを戻してリモートレポジトリにプッシュしてしまうと、他の人たちのコミット履歴とズレてエラーが発生する。迷惑＆嫌がられる\n\n#### git revert commitID\n- マージのUndo（リモートでもOK）\n- **コミット履歴: 残る**\n- 使い方\n  - 指定したマージ（commitID）のUndo :  `git revert \u003ccommitID\u003e`\n  - マージコミットUndo:  `git revert -m [1|2] \u003ccommitID\u003e`    (パターン番号: 1 - 現在のブランチ, 2- 派生ブランチ)\n  - リバートの打ち消し(revertコマンドを未実行状態に戻す): `git revert --abort`\n-  共同開発レポジトリではこちらを使うことを推奨（コミット履歴に残るから）\n\n### テスト準備\nmainブランチからmerge-test-devを作成して、テスト用コミット(c0〜c4)を実行\n```bash\ngit checkout main\ngit checkout -b merge-test-dev\n\necho \"add c0\" \u003e\u003e merge.md \u0026\u0026 git add merge.md \u0026\u0026 git commit -m \"c0\"\necho \"add c1\" \u003e\u003e merge.md \u0026\u0026 git add merge.md \u0026\u0026 git commit -m \"c1\"\necho \"add c2\" \u003e\u003e merge.md \u0026\u0026 git add merge.md \u0026\u0026 git commit -m \"c2\"\necho \"add c3\" \u003e\u003e merge.md \u0026\u0026 git add merge.md \u0026\u0026 git commit -m \"c3\"\necho \"add c4\" \u003e\u003e merge.md \u0026\u0026 git add merge.md \u0026\u0026 git commit -m \"c4\"\n```\n\nmainブランチに戻り、mainブランチから`merge-test-main`ブランチを作成\n\n```bash\ngit checkout main\ngit checkout -b merge-test-main\n\ngit l\n* a9ae509 (merge-test-dev) c4 - Yoichi Kawasaki, 3 minutes ago\n* 184c432 c3 - Yoichi Kawasaki, 3 minutes ago\n* a31d620 c2 - Yoichi Kawasaki, 3 minutes ago\n* b60231c c1 - Yoichi Kawasaki, 3 minutes ago\n* fa26181 c0 - Yoichi Kawasaki, 3 minutes ago\n* 3cc58f0 (HEAD -\u003e merge-test-main, main) update - Yoichi Kawasaki, 3 hours ago\n```\n\n### Undoテスト1: マージ成功後に元に戻す(git reset)\n\n`merge-test-main`ブランチにて、コミットc0をmergeする\n\n```bash\ngit merge fa26181    # fa26181 = c0 commit ID\n\n# merge.mdファイルチェック\ncat merge.md\nadd c0\n\n# ログチェック\ngit l \n* a9ae509 (merge-test-dev) c4 - Yoichi Kawasaki, 6 minutes ago\n* 184c432 c3 - Yoichi Kawasaki, 6 minutes ago\n* a31d620 c2 - Yoichi Kawasaki, 6 minutes ago\n* b60231c c1 - Yoichi Kawasaki, 6 minutes ago\n* fa26181 (HEAD -\u003e merge-test-main) c0 - Yoichi Kawasaki, 6 minutes ago\n```\n\n次に、コミットc1をmergeしてみる\n\n```bash\ngit merge b60231c     # b60231c = c1 commit ID\n\n# merge.mdファイルチェック\ncat merge.md\nadd c0\nadd c1\n```\n\nさらに、コミットc3をmergeしてみる\n```\ngit merge 184c432  # 184c432 = c3 commit ID (この場合、c3とその親にあたるc2 .. もマージされる)\n\n# merge.mdファイルチェック\ncat merge.md\nadd c0\nadd c1\nadd c2\nadd c3\n```\n\n次に、`git reset`で コミットc3のmergeを取り消して、c1 mergeの時点まで戻る\n\n```bash\n# コマンド履歴をみる\ngit reflog\n\n184c432 (HEAD -\u003e merge-test-main) HEAD@{0}: merge 184c432: Fast-forward\nb60231c HEAD@{1}: merge b60231c: Fast-forward\nfa26181 HEAD@{2}: merge fa26181: Fast-forward\n3cc58f0 (main) HEAD@{3}: checkout: moving from main to merge-test-main\n\n# コミットc1 b60231cのところまで戻る\ngit reset --hard b60231c\ngit l\n* a9ae509 (merge-test-dev) c4 - Yoichi Kawasaki, 14 minutes ago\n* 184c432 c3 - Yoichi Kawasaki, 14 minutes ago\n* a31d620 c2 - Yoichi Kawasaki, 15 minutes ago\n* b60231c (HEAD -\u003e merge-test-main) c1 - Yoichi Kawasaki, 15 minutes ago\n* fa26181 c0 - Yoichi Kawasaki, 15 minutes ago\n\n# merge.mdファイルチェックして、コミットc1のところまで戻っていることを確認\ncat merge.md\nadd c0\nadd c1\n```\n\n### Undoテスト2: マージ成功後に元に戻す(git revert)\n\n次に、再びコミットc3をmergeする\n\n```\ngit merge 184c432     # 184c432 = c3 commit ID (この場合、c3とその親にあたるc2 .. もマージされる)\n\n# merge.mdファイルをチェックしてコミットc3がマージされていることを確認\ncat merge.md\nadd c0\nadd c1\nadd c2\nadd c3\n\n# ログをみる\ngit l\n* a9ae509 (merge-test-dev) c4 - Yoichi Kawasaki, 71 minutes ago\n* 184c432 (HEAD -\u003e merge-test-main) c3 - Yoichi Kawasaki, 71 minutes ago\n* a31d620 c2 - Yoichi Kawasaki, 72 minutes ago\n* b60231c c1 - Yoichi Kawasaki, 72 minutes ago\n* fa26181 c0 - Yoichi Kawasaki, 72 minutes ago\n```\n\n次に、`git revert`で コミットc3のmergeを取り消して、コミットc2 mergeの時点まで戻る\n\n```bash\ngit revert 184c432   # コミットc3をRevert\n```\n\n次のようなeditぺーじに遷移するが、メッセージを書いて保存するとrevert完了\n\n![](assets/revert-output.png)\n\nログをみると次のようにrevertログが残っていることがわかる（一方 git resetでは取り消しログが残っていない）\n\n```bash\ngit l \n\n* 69f5860 (HEAD -\u003e merge-test-main) Revert \"c3\" - Yoichi Kawasaki, 2 minutes ago\n| * a9ae509 (merge-test-dev) c4 - Yoichi Kawasaki, 76 minutes ago\n|/\n* 184c432 c3 - Yoichi Kawasaki, 76 minutes ago\n* a31d620 c2 - Yoichi Kawasaki, 76 minutes ago\n* b60231c c1 - Yoichi Kawasaki, 76 minutes ago\n* fa26181 c0 - Yoichi Kawasaki, 76 minutes ago\n```\n\n### Undoテスト3: コンフリクトでマージ失敗(マージ未完了)(git merge --abort)\n\nまずはテスト c1まで戻す\n\n```bash\n# コミットc1 b60231cのところまで戻る\ngit reset --hard b60231c\ngit l\n* a9ae509 (merge-test-dev) c4 - Yoichi Kawasaki, 14 minutes ago\n* 184c432 c3 - Yoichi Kawasaki, 14 minutes ago\n* a31d620 c2 - Yoichi Kawasaki, 15 minutes ago\n* b60231c (HEAD -\u003e merge-test-main) c1 - Yoichi Kawasaki, 15 minutes ago\n* fa26181 c0 - Yoichi Kawasaki, 15 minutes ago\n```\n\n次に、merge.mdを編集してコミットc5を追加する\n\n```bash\necho \"add c5\" \u003e\u003e merge.md \u0026\u0026 git add merge.md \u0026\u0026 git commit -m \"c5\"\n\n# merge.mdを確認する\ncat merge.md\nadd c0\nadd c1\nadd c5\n\n# ログをみる\ngit l\n* 2d669b9 (HEAD -\u003e merge-test-main) c5 - Yoichi Kawasaki, 15 seconds ago\n| * a9ae509 (merge-test-dev) c4 - Yoichi Kawasaki, 16 minutes ago\n| * 184c432 c3 - Yoichi Kawasaki, 16 minutes ago\n| * a31d620 c2 - Yoichi Kawasaki, 16 minutes ago\n|/\n* b60231c c1 - Yoichi Kawasaki, 16 minutes ago\n* fa26181 c0 - Yoichi Kawasaki, 16 minutes ago\n```\n\n次に、コミットc3をmergeする。すると、次のようにコンフリクトが発生する\n\n```bash\ngit merge 184c432  #  184c432  = コミットc3のID \n\nAuto-merging merge.md\nCONFLICT (content): Merge conflict in merge.md\nAutomatic merge failed; fix conflicts and then commit the result.\n\n# merge.mdを見るとコンフリクトが確認できる\ncat merge.md\nadd c0\nadd c1\n\u003c\u003c\u003c\u003c\u003c\u003c\u003c HEAD\nadd c5\n=======\nadd c2\nadd c3\n\u003e\u003e\u003e\u003e\u003e\u003e\u003e 184c432\n```\n\nこの状態を元に戻したい。ここでは `git merge --abort`を使う\n\n```bash\ngit merge --abort\n\n# merge.mdをみて無事戻っていることを確認\ncat merge.md\nadd c0\nadd c1\nadd c5\n```\n\n### Undoテスト4: コンフリクトでマージ失敗（マージ未完了）(git reset)\n\n再びコミットc3をmergeしてみて、意図的にコンフリクトを発生させる\n\n```bash\n\ngit merge 184c432   #  184c432  = コミットc3のID \nAuto-merging merge.md\nCONFLICT (content): Merge conflict in merge.md\nAutomatic merge failed; fix conflicts and then commit the result.\n\n```\nあとは、さきほどのgit reset のときと同じように git reflogして git resetで戻すcommitIDを指定する\n\n```bash\ngit reflog\n2d669b9 (HEAD -\u003e merge-test-main) HEAD@{1}: reset: moving to HEAD\n2d669b9 (HEAD -\u003e merge-test-main) HEAD@{2}: commit: c5\n\ngit reset --hard 2d669b9\n# or \n# git reset --hard HEAD\n```\n\n\n## cherry-pick\n\n### cherry-pickの基本\n\n例えば PR (main -\u003e release)において差分コミットがc0, c1, c2 ... cNと合った場合に、c1, c2, c4だけ取り込みたい場合のどうするだろう？ `git merge \u003ccommitID\u003e`の場合、指定したcommitIDとその親に当たるcommitまで含めてmergeされてしまう（つまり c2をmergeするとその親にあたるc0, c1までも取り込まれる）。純粋に c1, c2, c4をmergeするには`cherry-pick`を使う\n\n使い方\n- シングル: `git cherry-pick \u003ccommitID\u003e`\n- 複数: `git cherry-pick \u003ccommitID1\u003e \u003ccommitID2\u003e ... \u003ccommitN\u003e`\n\n### 絵で比較するmerge vs cherry-pick\n\nこちらの記事の比較絵がわかりやすい。\nhttps://faun.pub/awesome-git-technique-for-partial-merge-7d64a7e62440\n\n最初の状態はこんなかんじ。\n\n![cherry-pick-0](assets/cherry-pick0.png)\n\n### git merge commit2\n`git merge`でcommit2を指定するパターン。\ngit mergeではブランチではなくrevision (commit)で取り込む事が可能。ただしその場合次のようにcommit2の親であるcommit1までも取り込んでしまう\n\n\n![cherry-pick-1](assets/cherry-pick1.png)\n\n### git cherry-pick commit4\n\ncherry-pickで必要なcommit4だけをマージする\n\n![cherry-pick-2](assets/cherry-pick2.png)\n\n### git cherry-pick commit5 commit6 commit7\n\ncherry-pickで複数commit指定してマージする\n\n![cherry-pick-3](assets/cherry-pick3.png)\n\n\n### テスト準備\n\nmainブランチから`cherry-dev`ブランチを作成して、テスト用コミット(c0〜c4)を実行\n\n```bash\ngit checkout main\ngit checkout -b cherry-dev\n\necho \"add test\" \u003e\u003e cherry0.md \u0026\u0026 git add cherry0.md \u0026\u0026 git commit -m \"c0\"\necho \"add test\" \u003e\u003e cherry1.md \u0026\u0026 git add cherry1.md \u0026\u0026 git commit -m \"c1\"\necho \"add test\" \u003e\u003e cherry2.md \u0026\u0026 git add cherry2.md \u0026\u0026 git commit -m \"c2\"\necho \"add test\" \u003e\u003e cherry3.md \u0026\u0026 git add cherry3.md \u0026\u0026 git commit -m \"c3\"\necho \"add test\" \u003e\u003e cherry4.md \u0026\u0026 git add cherry4.md \u0026\u0026 git commit -m \"c4\"\n```\n\nmainブランチに戻り、mainブランチからcherry-mainブランチを作成\n\n```bash\ngit checkout main\ngit checkout -b cherry-main\n\n# ログの確認\ngit l\n\n* 71eef9e (cherry-dev) c4 - Yoichi Kawasaki, 50 seconds ago\n* fcf29b8 c3 - Yoichi Kawasaki, 54 seconds ago\n* 466cecb c2 - Yoichi Kawasaki, 56 seconds ago\n* 33953c0 c1 - Yoichi Kawasaki, 59 seconds ago\n* 6baee64 c0 - Yoichi Kawasaki, 68 seconds ago\n```\n\n### git mergeテスト (cherry-pickとの動きの比較のための実施)\n\n`git merge`をつかって コミットc0とc1を`cherry-main`ブランチにmergeする。\n\n```bash\ngit merge 33953c0  # c1のcommit\n\ngit l\n* 71eef9e (cherry-dev) c4 - Yoichi Kawasaki, 2 minutes ago\n* fcf29b8 c3 - Yoichi Kawasaki, 2 minutes ago\n* 466cecb c2 - Yoichi Kawasaki, 2 minutes ago\n* 33953c0 (HEAD -\u003e cherry-main) c1 - Yoichi Kawasaki, 2 minutes ago\n* 6baee64 c0 - Yoichi Kawasaki, 2 minutes ago\n\nls -1 cherry*\ncherry0.md\ncherry1.md\n```\n`git merge \u003cc1 commit\u003e`なのに、c1の親のc0もマージされていることがポイント。これがgit mergeの動き\n\n次に、コミットc3を`cherry-main`ブランチにmergeする。 コミットc3を指定すると、その親であるc2,c1,c0もmergeされる。\n\n```\ngit merge fcf29b8 # c3のcommit \n\ngit l\n* 71eef9e (cherry-dev) c4 - Yoichi Kawasaki, 3 minutes ago\n* fcf29b8 (HEAD -\u003e cherry-main) c3 - Yoichi Kawasaki, 3 minutes ago\n* 466cecb c2 - Yoichi Kawasaki, 3 minutes ago\n* 33953c0 c1 - Yoichi Kawasaki, 3 minutes ago\n* 6baee64 c0 - Yoichi Kawasaki, 3 minutes ago\n\nls -1 cherry*\ncherry0.md\ncherry1.md\ncherry2.md\ncherry3.md\n```\n\n次に、git resetのおさらいを兼ねて、今のgit merge コミットc3を元に戻してみる\n\n```bash\ngit reflog\nfcf29b8 (HEAD -\u003e cherry-main) HEAD@{0}: merge fcf29b8: Fast-forward\n33953c0 HEAD@{1}: merge 33953c0: Fast-forward \u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c ここ\n3cc58f0 (main) HEAD@{2}: checkout: moving from main to cherry-main\n\n# ここでc1をmergeしたところまでもどる\ngit reset --hard 33953c0\n\ngit l\n* 71eef9e (cherry-dev) c4 - Yoichi Kawasaki, 5 minutes ago\n* fcf29b8 c3 - Yoichi Kawasaki, 5 minutes ago\n* 466cecb c2 - Yoichi Kawasaki, 5 minutes ago\n* 33953c0 (HEAD -\u003e cherry-main) c1 - Yoichi Kawasaki, 5 minutes ago\n* 6baee64 c0 - Yoichi Kawasaki, 5 minutes ago\n\nls -1 cherry*\ncherry0.md\ncherry1.md\n```\n\n### git cherry-pick テスト\n\nコミットc3だけを取り込むためにcherry-pickを使う。\n\n下記のようにcherry-pickでコミットc3を指定する\n```\ngit cherry-pick fcf29b8    # c3のcommit ID\n\n# c3だけが取り込まれていることがわかる\ngit l\n* 211b172 (HEAD -\u003e cherry-main) c3 - Yoichi Kawasaki, 8 minutes ago\n| * 71eef9e (cherry-dev) c4 - Yoichi Kawasaki, 8 minutes ago\n| * fcf29b8 c3 - Yoichi Kawasaki, 8 minutes ago\n| * 466cecb c2 - Yoichi Kawasaki, 8 minutes ago\n|/\n* 33953c0 c1 - Yoichi Kawasaki, 8 minutes ago\n* 6baee64 c0 - Yoichi Kawasaki, 8 minutes ago\n\nls -1 cherry*\ncherry0.md\ncherry1.md\ncherry3.md\n```\n\n### GitHubで演習 \n\n1. cherry-devブランチをpushして、PR (cherry-dev -\u003e main)を作成\n2. PRをマージ\n3. 新たにPR (main -\u003e release)を作成.\n  ただし、ここで全てのcommitをマージすると問題があると仮定する。c1+c3だけ先にマージしたい\n4. releaseブランチからrelease-hotfixというなのhotfixブランチを作成\n5. release-hotfixでc1+c3をcherry-pickしてorigin push\n6. PR (release-hotfix -\u003e release) のPRを作成 \n7. PRをマージ\n\n\n\n## PRレビュー\n\n### リモートブランチをfetchしてレビュー1 (remote-add + fetch)\n\nfoobarさんからPRがきた。それでPR元の修正内容を取り込みたい。foobarさんのブランチ(`fix-bug`)を取り込んで内容を確認する。ここでは対象リポジトリは`sample-plugin-hoge`とする\n\n\u003e 対象リポジトリ: git@github.com:foobar/sample-plugin-hoge.git\n\nまずは、foobarさんのリポジトリをfoobarという名前でremoteブランチとして追加\n\n```bash\n# git remote add origin https://github.com/user/repo.git\ngit remote add foobar https://github.com/foobar/sample-plugin-hoge.git\n```\n\nremoteブランチをチェック\n```bash\n$ git remote -v\norigin  ssh://git@github.com/yokawasa/sample-plugin-hoge (fetch)\norigin  ssh://git@github.com/yokawasa/sample-plugin-hoge (push)\nfoobar    https://github.com/foobar/sample-plugin-hoge.git (fetch)\nfoobar    https://github.com/foobar/sample-plugin-hoge.git (push)\n```\n\nリモートブランチをfetchしてローカルに取り込む\n\n```bash\n# git fetch remotename\ngit fetch foobar\n\n$ git branch -a\n* master\n  remotes/origin/HEAD -\u003e origin/master\n  remotes/origin/master\n  remotes/foobar/master\n  remotes/foobar/fix-bug\n```\n\n取り込んだブランチにスイッチ\n\n```bash\ngit co foobar/fix-bug\n```\n\nマージする場合は以下のようにします\n\n```bash\ngit co main\ngit merge foobar/fix-bug\ngit push origin main\n```\n\n### リモートBranchをfetchしてレビュー2 (PR#とブランチ名でfetch)\n\n上記「リモートブランチをfetchしてレビュー1」の別解。\n\nfoobarさんからPR(`PR#123`)がきた。それでPR元の修正内容を取り込みたい。foobarさんのブランチ(`fix-bug`)を取り込んで内容を確認する。ここでは対象リポジトリは`sample-plugin-hoge`とする\n\nまず、自分のローカルリポジトリにfoobarさんのブランチをフェッチします\n\n```bash\ngit fetch origin pull/123/head:sample-plugin-hoge\n```\n\n次に、フェッチしたブランチをチェックアウトします\n\n```bash\ngit checkout sample-plugin-hoge\n```\n\n## Subtree\n### add subtree\n\n取り込みたいリポジトリを、外部リポジトリに登録する\n\n```sh\n\nSUBTREE_NAME=github-sandbox\ngit remote add $SUBTREE_NAME git@github.com:yokawasa/github-sandbox.git\n```\n\n外部リポジトリに登録したものをサブディレクトリに登録する\n\n```sh\nSUBTREE_NAME=github-sandbox\ngit subtree add --prefix=${SUBTREE_NAME} --squash ${SUBTREE_NAME} main\n```\n\n### pull subtree\n\n```sh\nSUBTREE_NAME=github-sandbox\ngit subtree pull --prefix=${SUBTREE_NAME} --squash ${SUBTREE_NAME} main\n```\n\n## Tag\n\nリポジトリに付与するタグの管理コマンド\n\n### add tag\n\n```sh\n\n# tagging without comment\ngit tag TAG\n\n# tagging with comment\ngit tag -a TAG -m 'TAG comment'\n```\n\nThen, finally push the TAG to the origin\n\n```sh\n\ngit push origin TAG\n\n# alternative way\ngit push --tags\n```\n\n### check tags\n\n```sh\n# list tags\ngit tag\n\n# pattern match\ngit tag -l 'v2.1.*'\n\n# check specific tag\ngit check TAG\n```\n\n### delete tag\n\n```sh\ngit tag -d TAG\n```\n\n\n## Stash\n\n一時的にリポジトリの変更を退避させるコマンド。退避させることで、一時的にブランチをスイッチしたり、編集中のファイルがあるときにrebase（rebaseの時、コミットしていない一時変更のファイルがあるとstashしろと怒られるので）するのに役に立つ\n\n### 変更待避 (stash)してstash一覧表示\n\n```sh\n# 変更待避: 変更をstackに保存\ngit stash\n\n# stash一覧表示\ngit stash list\n```\n\n\u003e Output\n\n```\nstash@{0}: WIP on master: 9839bba Add typescript version of React app\nstash@{1}: WIP on master: 2fd45a3 Added Web App\n```\n\n### stashした内容を復元\n\n```sh\n# 最新のstashした変更を復元\ngit stash apply\n\n# 特定のstashした変更を復元\n# git stash apply stash@{n} # （nは0が0から始まる番号）\ngit stash apply stash@{1}\n```\n\n### stashした内容を削除\n\n```sh\n# 最初のstashした内容を削除  stash@{0}\ngit stash drop\n```\n\nstashした内容を復元して削除するにはpop。`git stash apply`した後に`git stash drop`\n\n```sh\ngit stash pop\n```\n### rebase時のstash対応\n\nrebaseの時、コミットしていない一時変更のファイルがあるとstashしろと怒られる。\n\n手動でなるならば\n\n```sh\ngit stash\ngit rebase upstream/main\ngit stash pop\n```\n\n`git rebase`に`--autostash`をつけるとstash / popを自動でやってくれる\n\n```sh\ngit rebase upstream/main --autostash\ngit rebase -i HEAD~2 --autostash\n```\n\nglobalにautostashをtrueにしておけばデフォルト化されてこの手間を省略できる\n\n```sh\ngit config --global rebase.autostash true\n```\n\nref: [開発Tips配信@ムーザルch](https://twitter.com/moozaru_ch/status/1633754692206600193)\n\n## APPENDIX\n\n### GitHub CLI\n\nGitHub CLI (gh)とは、GitHubに対する操作をコマンドラインで行うことができるユーティリティで、IssueやPull Request、Repository等の操作をCLIで行える。\n\nhttps://cli.github.com/manual/\n\n使用例） GitHub CLIでIssue一覧表示 (macOS)\n\n```sh\n# CLI installl\nbrew install gh\n\n# 認証設定\ngh auth login\n\n# Issue一覧表示\ngh issue list\n```\n\n#![](assets/gh-issue-list.png)\n\n### GitHubでmasterブランチをmainに変更\n\n手順は次の3ステップ:\n\n1. ブランチ名をmasterからmainに変更\n\n    ```sh\n    git branch -m master main\n    git push origin main\n\n    # もしくは masterブランチに移動してからmainに変更\n    git branch master\n    git branch -m main\n    git push origin main\n    ```\n2. GitHub上でデフォルトブランチをmainに変更\n\n    Settings → Default Branch項目で、Default Branchを`master`から`main`に変更\n\n3. 旧ブランチをリモートで削除\n\n    ```\n    git push origin :master\n    # or\n    git push --delete origin master \n    ```\n\n    ＊ ブランチ名を変更したら、旧ブランチ名にアクセスされると自動的にリダイレクトされる [ref](https://docs.github.com/ja/repositories/configuring-branches-and-merges-in-your-repository/managing-branches-in-your-repository/renaming-a-branch#about-renaming-branches)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyokawasa%2Fgithub-sandbox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyokawasa%2Fgithub-sandbox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyokawasa%2Fgithub-sandbox/lists"}