gitガッツリ触る
結構使っていないコマンドや、理解していない部分もあるのであらためて触ってみる
repo: yuki-snow1823/commit-sandbox: gitのあらゆるコマンド練習のリポジトリ
触りたいコマンドなど
✅ originとは何か、upstreamとは何かを説明できるか
リモートリポジトリのデフォルト名。ローカルだったらupstream。変更することもできる。
--set-upstreamしないとどこにpushすればいいか分からないので、git pushだけだとエラーになる
リモートリポジトリではなくリモートブランチの話
git push -u origin main
この-uが同じ意味を持っている
✅ rebaseとpullしたときの生え方の違い再確認
1本になるかどうか。「リ」ベースなので、ベースを付け替える
リベースは、現在のブランチを別のブランチの最新状態の後ろに積み直すと覚える
2本くらいのブランチでやっても良さが分からなかったが、より多くのブランチがある場合は良さそう
✅ リセットのコマンドを明確に
git reset --soft, --mixed, --hard の違いを確認
オプションは「戻した変更たちをエディタ上に残すかどうか」みたいに考えると良さそう
softが安全
ちなみにブランチも指定できる
✅ あとontoについても知りたい
✅ ブランチの付け替えをする方法
これは--ontoのことだった
✅ squashでまとめてコミットログをきれいにする
✅ blame
これはgithub上の方が見やすい
https://scrapbox.io/files/675f81bf8fff2684e09a02dc.png
✅ reflogで元に戻す
理解できたTIPS
gitの履歴の矢印が逆に見える表現が多い理由
mergeとrebaseの中止コマンド
--abort
グラフで可視化
git log --oneline --graph --all
VSCodeで変更の追跡(?)みたいなマージ後の操作はgit rebase --continueを実行していた
そもそもoriginとは
code:plain
❯ git push
fatal: The current branch main has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin main
リモートリポジトリのデフォルト名。ローカルだったらupstream。変更することもできる。
code:plain
remote add origin git@github.com:yuki-snow1823/commit-sandbox.git
これはoriginを登録しただけ
code:plain
❯ git push origin main
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 281 bytes | 281.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:yuki-snow1823/commit-sandbox.git
❯ git add README.md
❯ git commit -m "upstreamなしでpushしてみようとする"
1 file changed, 1 insertion(+)
❯ git push
fatal: The current branch main has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin main
つまり、--set-upstreamしないとローカルリポジトリがどのoriginを追跡すれば良いかわからないので
git pushとかだけでpushできない。上記のコマンドを実行すれば、git pushだけでプッシュできるようになる。
この追跡状態のブランチを上流ブランチっていうらしい。
rebaseとmerge
余談
git push -u origin 今のブランチ名 とするのが面倒
code: plain
# 現在のブランチ名を取得
current_branch=$(git rev-parse --abbrev-ref HEAD)
# 現在のブランチをリモートに push する
git push -u origin "$current_branch"
これ後で試す
まあタブキーでもいいけれども
https://scrapbox.io/files/673fcf108f711398f217d241.png
プルリクをマージした状態
ローカルでmainに戻してpullする
code:plain
hint: Pulling without specifying how to reconcile divergent branches is
hint: discouraged. You can squelch this message by running one of the following
hint: commands sometime before your next pull:
hint:
hint: git config pull.rebase false # merge (the default strategy)
hint: git config pull.rebase true # rebase
hint: git config pull.ff only # fast-forward only
hint:
hint: You can replace "git config" with "git config --global" to set a default
hint: preference for all repositories. You can also pass --rebase, --no-rebase,
hint: or --ff-only on the command line to override the configured default per
hint: invocation.
From github.com:yuki-snow1823/commit-sandbox
* branch main -> FETCH_HEAD
Updating 7c03730..624b6cb
Fast-forward
README.md | 1 +
1 file changed, 1 insertion(+)
rebase試すならローカルでマージしちゃダメそう
1. rebase用にリモートでプルリクをマージした
2. ローカルで別ブランチに行って、fetch
3. コマンド実行
code:plain
❯ git rebase main
Current branch rebase-test2 is up to date.
そういうわけではないっぽい。
mainを進めればいいのかも。mainでpullしてみる。
code:plain
❯ git pull origin main
hint: Pulling without specifying how to reconcile divergent branches is
hint: discouraged. You can squelch this message by running one of the following
hint: commands sometime before your next pull:
hint:
hint: git config pull.rebase false # merge (the default strategy)
hint: git config pull.rebase true # rebase
hint: git config pull.ff only # fast-forward only
hint:
hint: You can replace "git config" with "git config --global" to set a default
hint: preference for all repositories. You can also pass --rebase, --no-rebase,
hint: or --ff-only on the command line to override the configured default per
hint: invocation.
From github.com:yuki-snow1823/commit-sandbox
* branch main -> FETCH_HEAD
Updating 624b6cb..b4403bc
Fast-forward
README.md | 1 +
1 file changed, 1 insertion(+)
❯ git checkout rebase-test2
Switched to branch 'rebase-test2'
❯ git rebase main
Successfully rebased and updated refs/heads/rebase-test2.
~/Desktop/workspace/commit-sandbox rebase-test2
できた。「開発中にmainに入ってきたmainの変更を取り込んで、自身を先頭にする」と考えると良さそうかも
-fなしでもpushできた。
https://scrapbox.io/files/673fd20f8f711398f218058e.png
なんかミスってそうだな🤔
code:plain
❯ git push origin rebase-test3
To github.com:yuki-snow1823/commit-sandbox.git
! rejected rebase-test3 -> rebase-test3 (non-fast-forward) error: failed to push some refs to 'github.com:yuki-snow1823/commit-sandbox.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
mainを変更した上で別ブランチでrebaseしてからpushしたら行けた
GitHub上でもrebaseマージしてみる
https://scrapbox.io/files/673fd3a06ca46994ad6bd985.png
https://scrapbox.io/files/673fd3dba0fde0f333d8d305.png
良さそう
rebaseは、「リベースは、現在のブランチを別のブランチの最新状態の後ろに積み直す」と理解した
mergeコミットが作られないので、履歴が一本になってみやすくなる
/emoji/thinking.icon 疑問:上のrebase-test3がどこにも取り込まれずに残っているように見えるのはどうしようもない?
ローカルのmainに行ってpullないしrebaseしたらコンフリクトした
リモートの方はmergeでいいのかも。rebaseではなく
うまく行った
/emoji/tea.iconが、履歴を見ただけだとやっぱり何がいいのかよくわからんな
https://scrapbox.io/files/673fd9a38523a25a667aa641.png
https://www.youtube.com/watch?v=YkPCYrfPM2U
見てみる。
理解した。複数ブランチがある場合はこれがきれいになりそう。
2本でやってたからよくわからなかったんだわ。
余談:マージやリベースを一旦やり直す
git merge --abort
git rebase --abort
code:plain
❯ git merge rebase-test3
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.
❯ git merge --abort
git reset系のコマンド試す
まずはざっくり理解
addやcommitを取り消せるコマンド
reset --hard:ワーキングツリー、ステージングエリア、コミットを全て取り消す。完全に元の状態に戻す。
reset --mixed(デフォルト):コミットとステージングエリアを取り消し、変更はワーキングツリーに残す。
reset --soft:コミットのみを取り消し、変更はステージングエリアに残す。
※ステージングはaddした後の場所。インデックスって呼ぶ人もいるっぽい。
code:plain
commit e45d4f67baaaaaaaa1906 (HEAD -> main) Author: yuki-snow1823
Date: Fri Nov 22 10:36:23 2024 +0900 mainで9行目を追加。これはresetで取り消します。
単純にコミットしてgit logで確認
git reset --soft HEAD^
code:plain
Date: Fri Nov 22 10:04:45 2024 +0900
Merge pull request #5 from yuki-snow1823/rebase-test4 テストブランチで8行目を追加したリベースのテスト
1番上がこれになった
ただ、手元に変更は残っている。ステージングもされている。コミットを戻せた感じ
GUIでいうところの、コミットを取り消すと同じそうだ
git reset --hard HEAD^
code:plain
HEAD is now at 5439b3a Merge pull request #5 from yuki-snow1823/rebase-test4 普通にコミット、ステージングにしたファイルが消えて、mainからpullできますよという表示が出てしまった
ステージングにしたファイルも消えたことに注目
reset --mixed
ステージングから外された
これらのコマンドは、そのブランチの中のちょっとした差分とかであれば問題なさそうだった
試しにそのブランチの結構前まで戻してみる
https://scrapbox.io/files/673fe3b8216cefc295f24630.png
今こういう感じ
logはこう
code:plain
commit 5bc6d84b325cdf345ea8c0f34d3dfa4e4e2a204c (HEAD -> main, origin/main)
Author: yuki-snow1823
Date: Fri Nov 22 10:45:11 2024 +0900
resetで消えるか2
commit ec1235b8a04e64807f02eb5acbd9a8f97efc0ac4
Author: yuki-snow1823
Date: Fri Nov 22 10:44:58 2024 +0900
resetで消えるか1
commit 79ae6bcfe3cf580ede4a95bb99022f984ef1243e
Author: yuki-snow1823
Date: Fri Nov 22 10:39:53 2024 +0900
resetで取り消さないコミット
「 resetで取り消さないコミット」まで戻してみる
ステージングに変更を入れつつgit reset --soft 79ae6bcfe3cf580ede4a95bb99022f984ef1243e
今ステージングしているやつだけではなく
/emoji/bulb.icon【重要】「resetで消えるか2,1」の変更もステージングに残った
これを全部まとめてpushしようとしてみる
多分エラーになるはず
なった
強制pushしたら思ったとおり全部まとまって履歴が変わった
完全理解した
https://scrapbox.io/files/673fe4e132d773946d5d10c6.png
余談:Gitの矢印は逆に見える理由
ontoとは
聞いたことがあったけど多分1回くらいしか使ってないので思い出せない
rebaseのオプションっぽい?
現在の作業ブランチの内容を他のベース(基底)ブランチの上に移し替えることができる
作業を付け替えるってことか
code:plain
git rebase --onto <newbase> <upstream> <branch>
<newbase>: リベースを適用する新しい基点(ベース)。
<upstream>: リベースで取り除く古い基点(ここから始まるコミットは除外される)。
<branch>: リベース対象のブランチ。省略すると現在チェックアウト中のブランチが対象。
やりたかった作業の付け替えと同じかも
やってみる
onto-1で1行追加
onto-2で1行追加
ここで、1に2の作業を生やしたい
1でgit rebase --onto onto-1 onto-2実行か?
git rebase --onto どこへ どこから どのブランチを って書いてくれている方がいた
なるほど、コミットも指定できるっぽい
git rebase --onto onto-1 61553cd780ea3f5eccb6e54b9103343723df8f7 onto-2
code:plain
Your branch and 'origin/onto-2' have diverged,
and have 1 and 1 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
2で実行したのが良くなかったかも
いや1で実行できてた。2に勝手に移動した。https://scrapbox.io/files/674117946d4fadb3a003dfe5.png
?
code:plain
GPT相談
<newbase> = onto-1
新しい基点として onto-1 (D) を指定。
<upstream> = 61553cd780ea3f5eccb6e54b9103343723df8f7
F 自身を指定してしまっています。
これにより、git は F 以降のコミットを取得しようとしますが、Fはブランチの最後なので、リベがなくなります。
結果:
何も変更されず、onto-2 が onto-1 に移動したように見える。
最後のコミットに対して実行するようなものではない?
git rebase --onto onto-1 main onto-2これでも同じ挙動になった
--ontoについてもう少し調査してみる
code:plain
# git rebase --onto {本来親にしたかったブランチ} {間違って親にしてしまったブランチ名} {親を変更する作業ブランチ名}
$ git rebase --onto origin/master work/A work/B
余談
git log --oneline --graph --all便利だった
code:plain
* a088a06 (origin/onto-4, onto-4) onto-4で追加した行
| * 9462ed6 (HEAD, origin/onto-3, onto-3) onto-3で追加した行
|/
onto-4上で、実行
code:plain
* 52fd00c (HEAD -> onto-4) onto-4で追加した行
* 9462ed6 (origin/onto-3, onto-3) onto-3で追加した行
| * a088a06 (origin/onto-4) onto-4で追加した行
|/
1本になった
git rebase --onto onto-3 main onto-4
でもブランチは4にいる
code:plain
いいえ、カレントブランチを onto-3 にチェックアウトする必要はありません。
git rebase は、リベース中のカレントブランチが変更される対象となるため、そのまま onto-4 にいる状態で進めて問題ありません。
状況の整理
現在、onto-4 ブランチ上で git rebase --onto onto-3 main onto-4 を実行しています。
このコマンドは、main を基点として分岐している onto-4 のコミットを、onto-3 の先に再配置するものです。
なるほど
なんかやりたいことと違うな...🤔
単純に2つブランチがあって、1つは正しい、1つは生やすの間違えた場合
間違えた方を正しい方につけて、正しいブランチ名のまま作業したい
そもそもこの考えが間違ってる?色々したけどできないっぽい
squashでコミットをまとめる
onelineでログを出してみた
code:plain
623b13b (HEAD -> main) squash3行目
9ee2f5f squash2行目
f52fe01 squash1行目
これをまとめたいと考える
2と3をまとめてみよう
git rebase -i HEAD~2
code:plain
pick 9ee2f5f squash2行目
pick 623b13b squash3行目
# Rebase f52fe01..623b13b onto f52fe01 (2 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
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
~
"~/Desktop/workspace/commit-sandbox/.git/rebase-merge/git-rebase-todo" 27L, 1146B
スカッシュしたい一連のコミットのうち、最も古いコミット以外のコミットの行頭の pick を s(または squash)に変更します。
今回は2に3をまとめたいので、3のpickをsにする
保存したところ、コミットメッセージの画面になった
code:plain
# This is a combination of 2 commits.
# This is the 1st commit message:
squash2行目
# This is the commit message #2: squash3行目
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date: Mon Dec 16 09:54:12 2024 +0900
#
# interactive rebase in progress; onto f52fe01
# Last commands done (2 commands done):
# pick 9ee2f5f squash2行目
# squash 623b13b squash3行目
# No commands remaining.
# You are currently rebasing branch 'main' on 'f52fe01'.
#
# Changes to be committed:
# modified: README.md
#
~
~
~
~
"~/Desktop/workspace/commit-sandbox/.git/COMMIT_EDITMSG" 24L, 610B
すると次はコミットメッセージを編集する画面になります。ここでは、スカッシュしたいコミットのメッセージを残して、それ以外のコミットのメッセージは削除します。編集はまたインサートモードで行います。
code:plain
a27c17a (HEAD -> main) squash2行と3行目をまとめたよ
f52fe01 squash1行目
まとまった
間に余計なコミット挟んでみる
code:plain
pick df5b861 squashしたいやつ1
pick fd38a48 squashの間に挟まるやつ
pick 6030963 squahしたいやつ2
1と2をまとめる
開いたエディターでインサートモードに入ったら、次のようにスカッシュしたいコミットが連続するように並べ替えます。また先ほどと同様に最も古いものを除くスカッシュしたいコミットの行頭の pick を s(または squash)に変更します。
code:plain
pick fd38a48 squashの間に挟まるやつ
pick df5b861 squashしたいやつ1
s 6030963 squahしたいやつ2
こうかな?
code:plain
pick fd38a48 squashの間に挟まるやつ
pick 6030963 squahしたいやつ2
pick 1b9227e 間をまとめた
思ったようにならなかった🤔
インタラクティブモードでは、古い方が上に来ている!
リベンジ
code:plain
pick 01c4b77 squashしたい1
pick eab9e2f したくない
pick 8c06f22 squashしたい2
2を上にするのか、1を下にするのか
→1を下にするのが適切っぽい。(したくない、より新しくする)
code:plain
pick eab9e2f したくない
pick 01c4b77 squashしたい1
s 8c06f22 squashしたい2
code:plain
pick c99cf6f したくない
pick 0517528 squashしたい1
まとまった。ちょっとあまり理解できない挙動だった。コンフリクトしたのもあるかも?
あまりコミットを跨いだrebaseはしたくないと思った。
reflog
code:plain
d6e842b (HEAD -> main) HEAD@{0}: commit: 消したくない
f47bddb HEAD@{1}: commit: 消したい
d639fcc HEAD@{2}: commit: reflogの学習開始
消したくないというか、消したいに戻したいケース
git reset --hard HEAD@{1}
戻れたし、問題なく操作できた。
さらにreflogする
code:plain
f47bddb (HEAD -> main, origin/main) HEAD@{0}: reset: moving to HEAD@{1}
d6e842b HEAD@{1}: commit: 消したくない
f47bddb (HEAD -> main, origin/main) HEAD@{2}: commit: 消したい
d639fcc HEAD@{3}: commit: reflogの学習開始
全てを元に戻したいときはまた
git reset --hard HEAD@{1}
かな?
code:plain
git reset --hard HEAD@{1}
HEAD: is: No such file or directory
HEAD: now: No such file or directory
HEAD: at: No such file or directory
HEAD: d6e842b: No such file or directory
HEAD: 消したくない: No such file or directory
d6e842b (HEAD -> main, origin/main) 消したくない
f47bddb 消したい
d639fcc reflogの学習開始
no suchが色々でたが、得たい結果にはなった。すごい