- 投稿日:2021-08-09T23:59:20+09:00
【Git】mergeとrebase
Gitでは、2つのブランチの履歴を統合する方法として merge と rebase の2つが用意されています。私自身、rebase についてよくわかっておらず、「どんな時でも merge!」派だった過去があるのですが、 rebase を理解できてからは merge と rebase を使い分けられるようになりました。 今日は、merge と rebaseの違いについてまとめていきます。 確認環境 Mac git version 2.30.0 前提 各コマンドの使い方やオプションについての説明はここでは省略させていただきます featureブランチにdevelopブランチを統合する、という操作をそれぞれのコマンドで実行していきます git log コマンドに使用しているオプションについてはこちら git-log からご確認ください merge 以下のような履歴を持つリポジトリを使います。 % git log --graph --pretty=format:"%h %s" develop-merge feature-merge * 49ea0ef develop-merge first commit | * deefe27 feature-merge first commit |/ * 09c96b7 first commit develop-mergeブランチ、feature-mergeブランチ、それぞれに変更が入っています。featureブランチにdevelopブランチをmergeしてみます。すると、以下のようになります。 % git switch feature-merge Already on 'feature-merge' % git merge develop-merge # コンフリクトが発生しました。解消は割愛させていただきます。 [feature-merge 8b3ec25] Merge branch 'develop-merge' into feature-merge % git log --graph --pretty=format:"%h %s" develop-merge feature-merge * 8b3ec25 Merge branch 'develop-merge' into feature-merge |\ | * 49ea0ef develop-merge first commit * | deefe27 feature-merge first commit |/ * 09c96b7 first commit 8b3ec25 という新しいマージコミットが生まれています。また、マージコミットの親となるコミットが2つ(49ea0ef と deefe27)になり、枝分かれしています。このようにmergeコマンドを使用すると、今までの履歴に影響を与えずに新しいコミットを生み出し2つのブランチの履歴を統合します。 ※FastForward状態になるとマージコミットが生まれません。ここでは説明を割愛します。 rebase mergeの例と同様、以下のような履歴を持つリポジトリを使います。 % git log --graph --pretty=format:"%h %s" develop-rebase feature-rebase * 49ea0ef develop-merge first commit | * deefe27 feature-merge first commit |/ * 09c96b7 first commit develop-rebaseブランチ、feature-rebaseブランチ、それぞれに変更が入っています。featureブランチにdevelopブランチをrebaseしてみます。すると、以下のようになります。 % git switch feature-rebase Switched to branch 'feature-rebase' % git rebase develop-rebase # コンフリクトが発生しました。解消は割愛させていただきます。 [detached HEAD 9159f39] feature-merge first commit 1 file changed, 1 insertion(+) Successfully rebased and updated refs/heads/feature-rebase. % git log --graph --pretty=format:"%h %s" develop-rebase feature-rebase * 9159f39 feature-merge first commit * 49ea0ef develop-merge first commit * 09c96b7 first commit 先ほどのmergeの例とは違って、履歴が一直線になりました。また、新たなコミットも生まれていません。 ですが、よくみてみると、 feature-merge first commit というメッセージのコミットのcommitIDが変わっています。 rebase前 deefe27 feature-merge first commit rebase後 9159f39 feature-merge first commit rebaseコマンドを実行すると、rebase先のブランチの先頭コミット(今回はdevelop-rebaseの49ea0ef)に対して、現在チェックアウトしているブランチの新しい変更(今回はfeature-rebaseのdeefe27)を適応する、といったことが行われます。このような挙動によって、mergeの時とは違って履歴が一直線になります。またdeefe27コミットはIDが変わります。 merge と rebase しばしば、「rebaseを使うとコミットの履歴が綺麗になる」と言われますが、上記のように、一直線の履歴になる、マージコミットがない、といったことがそのように言われる理由にだと思います。 しかし、rebaseはmergeと違ってコミット自体を書き換えてしまいます。そのため、メンバーと共有しているリポジトリ内でrebaseを使うと他のメンバーがpullできない、pushできない、といった事態も起こりかねません。このあたりはチームによって運用が異なると思います。 使い分けの一案 私が実際に行っている使い分けです。あくまで一案になります。 開発の最新となるdevelopブランチからfeatureブランチをきる featureブランチで作業を行い、コミットする featureブランチにdevelopブランチをrebaseする developブランチに対してfeatureブランチをプルリクする developブランチにfeatureブランチをmergeする(実際はプルリクエストのマージ) 上記のように作業を行うことで、featureブランチの履歴は一直線になり、マージコミットなども入らずに、レビューがしやすいです。一方、開発の中心となるdevelopブランチにはmergeを行います。こうすることで、developブランチの履歴にはmergeコミットが残り、どのタイミングでどのプルリクエストがマージされたのかが分かりやすくなります。
- 投稿日:2021-08-09T19:06:43+09:00
任意のgit commitへ一時的に巻き戻す。
備忘録です。 git コマンド # ワーキングツリーとインデックスの内容を stash に一時保存する。 git stash # コミットIDを探す。 git log # 過去のコミットに戻る git switch -d <コミットID> # 過去に戻れたか確認: git log --all --oneline 使い道の例 他人のコードを読んでいるとき。最終的な成果物より、開発手法や過程を見たいと思う時がある。 あるバージョンのコードをビルドしたいとき。 単純に前の状態へ戻したいとき。
- 投稿日:2021-08-09T12:09:38+09:00
【Git】プルリクエスト前に複数のコミットを1つにまとめてコミットログを読みやすくする
はじめに 細かいコミットが大量にあったり、メモレベルのコミットがあったりすると、プルリクエスト時にコミットログが追いにくくなり、レビューアに負担がかかる場合があります。 rebaseコマンドを利用して複数のコミットログを1つにまとめる方法をご紹介します。 前提条件・環境情報 Windows10 開発環境 Visual Studio 2019 .NET Framework 4.7 C# git本体がインストール済みであること vimの基本操作(編集と保存)ができること git本体以外の環境は適宜読み換えてください。 gitコマンドを利用した方法となりますので、環境に依存しない普遍的な内容となっています。 コミットをまとめる前の変更履歴がリモートリポジトリにPushされている場合、コンフリクトが発生します。 「git push -f origin 」で強制的に変更する必要があります。 記事最後の参考資料も参考にしてみてください。 題材にするソースコードとコミットログ ソースコード 単純なコンソールプロジェクトです。 using System; namespace ConsoleApp1 { internal class Program { private static int Main(string[] args) { try { // コメントを追加 var str = "これはテストです"; System.Console.WriteLine(str); return 0; } catch (Exception ex) { System.Console.WriteLine(ex.ToString()); return -1; } } } } コミットログ コミットログが新しい順で表示されます。 $ git log --oneline 564627d (HEAD -> master) #1 CodeMaidで綺麗にした 1c4520d #1 正常系・異常系の戻り値を指定 57eef82 #1 try-catchで囲む 891e7e8 #1 System.Console.WriteLineを追加 01bc665 #1 コメントを追加 13fcfba #1 「var str」を追加 aed97a0 プロジェクト ファイルを追加します。 f15572e .gitignore および .gitattributes を追加します。 複数のコミットを1つにまとめる方法 コミットのまとめ先(例えば「13fcfba」とする)の1つ前のコミットID(aed97a0)を指定します。 git rebase -i aed97a0 vimでrebaseの指示モードになります。 pick 13fcfba #1 「var str」を追加 pick 01bc665 #1 コメントを追加 pick 891e7e8 #1 System.Console.WriteLineを追加 pick 57eef82 #1 try-catchで囲む pick 1c4520d #1 正常系・異常系の戻り値を指定 pick 564627d #1 CodeMaidで綺麗にした # Rebase aed97a0..564627d onto 57eef82 (6 commands) # # Commands: # p, pick <commit> = use commit # r, reword <commit> = use commit, but edit the commit message # e, edit <commit> = use commit, but stop for amending # s, squash <commit> = use commit, but meld into previous commit # f, fixup <commit> = like "squash", but discard this commit's log message まとめるコミットIDのpickをsまたはsquashに変更します(「i」で編集モードにして変更する)。 1行目がコミットのまとめ先になるので、pickのままにします(sにするとrebaseエラーになる)。 pick 13fcfba #1 「var str」を追加 s 01bc665 #1 コメントを追加 s 891e7e8 #1 System.Console.WriteLineを追加 s 57eef82 #1 try-catchで囲む s 1c4520d #1 正常系・異常系の戻り値を指定 s 564627d #1 CodeMaidで綺麗にした 保存して終了します(Escでノーマルモードにして、「:wq」で保存してvimを終了する)。 :wq vimでコミットコメントの指示モードになります。コミットをまとめるにあたり、新しいコミットログが求められるからです。 # This is a combination of 6 commits. # This is the 1st commit message: #1 「var str」を追加 # This is the commit message #2: #1 コメントを追加 # This is the commit message #3: #1 System.Console.WriteLineを追加 # This is the commit message #4: #1 try-catchで囲む # This is the commit message #5: #1 正常系・異常系の戻り値を指定 # This is the commit message #6: #1 CodeMaidで綺麗にした コミットログを書き換えて、保存して終了します。 issueとコミットを紐づけるために「#2」のように先頭にissue番号を記載しますが、 シャープ「#」はコメントアウト(無効なコメント)とみなされるので、先頭に半角スペースを入れるとよいでしょう。 # This is a combination of 6 commits. # This is the 1st commit message: #1 XXXバッチの新規作成 複数のコミットが1つにまとまりました。 $ git log --oneline af7f258 (HEAD -> master) #1 XXXバッチの新規作成 aed97a0 プロジェクト ファイルを追加します。 f15572e .gitignore および .gitattributes を追加します。 差分でも複数のコミットが1つにまとまったことが確認できます。 # 差分を確認 # git diff 変更前のコミットID 変更後のコミットID git diff aed97a0 af7f258 diff --git a/ConsoleApp1/Program.cs b/ConsoleApp1/Program.cs index ea9bacc..156cfdc 100644 --- a/ConsoleApp1/Program.cs +++ b/ConsoleApp1/Program.cs @@ -1,15 +1,26 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace ConsoleApp1 { - class Program + internal class Program { - static void Main(string[] args) + private static int Main(string[] args) { + try + { + // コメントを追加 + var str = "これはテストです"; + + System.Console.WriteLine(str); + + return 0; + } + catch (Exception ex) + { + System.Console.WriteLine(ex.ToString()); + + return -1; + } } } -} +} 間違えた時は... コミットログにチケット番号が記載されていなかったのでコミットコメントを修正したい amendオプションで直前のコミットを書き換えることができます。 git commit --amend -m "#1 XXXバッチの新規作成" $ git log --oneline 1632572 (HEAD) #1 XXXバッチの新規作成 aed97a0 プロジェクト ファイルを追加します。 f15572e .gitignore および .gitattributes を追加します。 rebaseの指示モードでまとめ先のコミットもsquashにしてしまった コミットのまとめ先が分からないのでCannot 'squash' without a previous commitというエラーメッセージが表示されます。 この場合、git rebase --abortで操作を取り消してください。 rebase自体を間違えたのでやり直したい reflogコマンドで戻したい履歴を確認します。 今回の場合、「HEAD@{16}」時点まで戻したいとします。 $ git reflog af7f258 (HEAD -> master) HEAD@{0}: rebase (finish): returning to refs/heads/master af7f258 (HEAD -> master) HEAD@{1}: rebase (squash): #1 XXXバッチの新規作成 b85537d HEAD@{2}: rebase (squash): # This is a combination of 5 commits. a4bf388 HEAD@{3}: rebase (squash): # This is a combination of 4 commits. 84fefd5 HEAD@{4}: rebase (squash): # This is a combination of 3 commits. 31331f7 HEAD@{5}: rebase (squash): # This is a combination of 2 commits. 13fcfba HEAD@{6}: rebase (start): checkout aed97a0 564627d HEAD@{7}: rebase (abort): updating HEAD 564627d HEAD@{8}: reset: moving to HEAD@{7} 2168520 HEAD@{9}: rebase (squash): # This is a combination of 5 commits. f1184fd HEAD@{10}: rebase (squash): # This is a combination of 4 commits. fa651ab HEAD@{11}: rebase (squash): # This is a combination of 3 commits. 6b60eb4 HEAD@{12}: rebase (squash): # This is a combination of 2 commits. 13fcfba HEAD@{13}: rebase (start): checkout aed97a0 564627d HEAD@{14}: rebase (finish): returning to refs/heads/master 564627d HEAD@{15}: rebase (start): checkout aed97a08 564627d HEAD@{16}: commit: #1 CodeMaidで綺麗にした 1c4520d HEAD@{17}: commit: #1 正常系・異常系の戻り値を指定 57eef82 HEAD@{18}: commit: #1 try-catchで囲む 891e7e8 HEAD@{19}: commit: #1 System.Console.WriteLineを追加 01bc665 HEAD@{20}: commit: #1 コメントを追加 13fcfba HEAD@{21}: commit: #1 「var str」を追加 aed97a0 HEAD@{22}: commit: プロジェクト ファイルを追加します。 f15572e HEAD@{23}: commit (initial): .gitignore および .gitattributes を追加します。 指定した時点までのコミットを打ち消します。 コミットをなかったことにするので注意して操作してください。 必要に応じてバックアップをとっておくことをお勧めします。 git reset --hard HEAD@{16} 元に戻っていることを確認します。 $ git log --oneline 564627d (HEAD -> master) #1 CodeMaidで綺麗にした 1c4520d #1 正常系・異常系の戻り値を指定 57eef82 #1 try-catchで囲む 891e7e8 #1 System.Console.WriteLineを追加 01bc665 #1 コメントを追加 13fcfba #1 「var str」を追加 aed97a0 プロジェクト ファイルを追加します。 f15572e .gitignore および .gitattributes を追加します。 参考資料 rebase -i でコミットをまとめる - Qiita Git squashで複数のコミットを1つでまとめる - dev.yakuza git rebase -i でコミットをまとめて履歴を綺麗にしよう! | WWWクリエイターズ
- 投稿日:2021-08-09T10:53:15+09:00
Git、GitHubそれぞれで、リポジトリ作成時のデフォルトブランチを設定する方法
昨年より、GitHubで作成されたリポジトリのデフォルトブランチは main になりました。 The default branch for newly-created repositories is now main また、Gitプロジェクトとしても初期ブランチ名をmaster以外に変更する検討が進められています。 Regarding Git and Branch Naming (上記リンクはこちら、 github/renamingから飛ぶことができます。) 現状、Gitではmasterブランチがデフォルトブランチとして自動的に作成されますが、バージョン2.28より、初期ブランチが指定できるようになりました。 Gitでデフォルトのブランチを変更する 環境 Mac git version 2.30.0 説明 gitのバージョンが2.28以上である必要があります。 2.28で使えるようになった init.defaultBranch を使います。 新規リポジトリを作成する場合にデフォルトブランチを main にしたい場合は以下のコマンドを実行します。 $ git config --global init.defaultBranch main この先gitコマンドで新しく作成するリポジトリのデフォルトブランチは main になります。既存のリポジトリのデフォルトブランチが変更されることはありません。 実験 init.defaultBranch に何も設定していない状態でリポジトリを作成すると、デフォルトブランチは master になります。 $ mkdir sample $ cd sample $ git init hint: Using 'master' as the name for the initial branch. This default branch name hint: is subject to change. To configure the initial branch name to use in all hint: of your new repositories, which will suppress this warning, call: hint: hint: git config --global init.defaultBranch <name> hint: hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and hint: 'development'. The just-created branch can be renamed via this command: hint: hint: git branch -m <name> Initialized empty Git repository in /xxxx/sample/.git/ $ touch test.txt $ git add . $ git commit -m "first commit" [master (root-commit) c05650c] first commit 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test.txt $ git branch * master git init を行うと、 hint としてデフォルトブランチの名前を変えられること、既存ブランチのrenameの方法も出力されていますね。 続いて、デフォルトブランチを main にしてみます。 git config --global init.defaultBranch main この状態でリポジトリを作成してみます。 $ mkdir sample-main $ cd sample-main $ git init Initialized empty Git repository in /xxxx/sample-main/.git/ $ touch test.txt $ git add . $ git commit -m "first commit" [main (root-commit) 563d9a9] first commit 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test.txt $ git branch * main デフォルトブランチが main になりました。 GitHubでデフォルトのブランチを変更する 説明 GitHubでもデフォルトのブランチを変更することができます。 main から変更する理由はあまりないかなと思いますが、CIだったりなんらかの理由で master にしたいこともあるかもしれません。 個人アカウント配下リポジトリ 以下のリンクにアクセスし、 Repository default branch を変更します。 https://github.com/settings/repositories 最初にアクセスすると main になっています。こちらを master 、もしくはデフォルトにしたいブランチを入力し Update ボタンを押すことで設定完了です。 GitHub Enterprise、Organization配下リポジトリ それぞれ以下のリンクにアクセスし、変更します。 https://github.com/organizations/YOUR-ORGANIZATION/settings/repository-defaults https://github.com/enterprises/YOUR-ENTERPRISE/settings/member_privileges 既存のリポジトリのデフォルトブランチをrenameする GitHub上で、既存のリポジトリのデフォルトブランチを変更することができます。 GitHub上のリポジトリ > Settings > Branches > Default branch を変更します。 こちらでGitHub上のデフォルトブランチをrenameすることはできますが、このリポジトリをcloneしているメンバーのローカルのブランチ名は変わりません。Web上で変更する際に、どのようなコマンドを打てば良いのかが出てくるので、そちらをローカルで実行する必要があります。 詳しくはこちら Renaming existing branches を参照ください。 最後に Regarding Git and Branch Naming には以下のような記述があります。 As a first step, Git will add a mechanism to allow users to specify the default used as the name of the first branch when creating a new repository. 今後、 init.defaultBranch の値のデフォルト値そのものが main になるんではないかと思われます。この点を考えると、今後作るリポジトリのデフォルトは main で良いのかもしれませんね。
- 投稿日:2021-08-09T08:34:27+09:00
【Git】ブランチ名を変更する方法(リモート・ローカル)
対象者 ローカルブランチ名を変更したい方 目的 ローカルブランチ名を変えてより他者にわかりやすいブランチ名に変更すること 実際の手順と実例 1.ローカルブランチ名の変更方法 下記コマンドで変更できます $ git branch -m <現在のブランチ名> <新しいブランチ名> これで変更できます。 作成後にこれでは分かりくい!と感じたときにおすすめです。 2.リモートブランチ名の変更方法 $ git branch -m 古いブランチ名 新しいブランチ名 $ git push -u origin 現在のブランチ名 $ git push origin :リモートのブランチ名 もしくは、GitHub上でも変更できます。 投稿者コメント なんだかブランチ名がわかりにくいと思って変更方法調べてみました。そもそも最初からわかりやすい名前付けていればよかったのですが、、、、、 My Profile プログラミング学習歴3ヶ月目のアカウントです! プログラミングスクールで学んだ内容や自分が躓いた箇所等のアウトプットの為に発信しています。 また、プログラミング初学者の方にわかりやすく、簡潔にまとめて情報共有できればと考えています。 もし、投稿した記事の中に誤り等ございましたら、コメント欄でご教授いただけると幸いです。