5 ms·
The disconnect between git's beautiful internal model of blobs, a tree of commits, and pointers to commits, and the command line interface is so wild. All of th
by lalaithion 2y ago
The disconnect between git's beautiful internal model of blobs, a tree of commits, and pointers to commits, and the command line interface is so wild. All of these recipes are unintuitive even if you have a firm grasp of git's model; you also need to know the quirks of the commands! To just look at the first one... wouldn't it be more intuitive for the command line interface to be:
# this command exists already;
$ git switch -c some-new-branch-name
# is there a command that simply moves a branch from one commit to another without changing anything else? It feels like it should be possible given how git works.
$ git move-branch master HEAD~
- pitaj 2y agoI prefer just using `git switch` because it's easy to remember the flags (and the position of arguments), but you're right, there is a simpler way: git switch -c some-new-branch-name git branch -f master HEAD~
- DangitBobby 2y agoYou should also be able to do git branch -f master origin/master
- pitaj 2y agoThis doesn't work if your local master was already ahead of origin
- DangitBobby 2y agoIndeed, as with all of these examples exceptions will apply and, it's a good idea to check the log before taking any such action. I believe your example also depends on exactly how many commits you've made that need to be moved. In any case, it depends on me remembering exactly what `~` signifies.
- lalaithion 2y agoGood to know! Thanks for the tip.
- neild 2y agoThe "move a branch from one commit to another without changing anything" command is "git reset". "git reset --hard" is "...and also change all the files in the working directory to match the new branch commit". "git reset --soft" is "...but leave the working directory alone".
- rav 2y agoActually, "git reset --soft" moves the current branch to another commit, without moving the index (aka staging area) along with it, whereas "git reset" (aka "git reset --mixed") moves the current branch AND the index to another commit. I really couldn't wrap my head around it before I had gone through "Reset demystified" [1] a couple times - it's not a quick read but I can strongly recommend it. [1] https://git-scm.com/book/en/v2/Git-Tools-Reset-Demystified https://git-scm.com/book/en/v2/Git-Tools-Reset-Demystified
- lalaithion 2y agogit reset only works if you're on the branch you want to move, which is why every one of these example flows has you create your new branch, then do the reset, then switch to the new branch, instead of just allowing you to move a branch you're not on.
- rav 2y agoFor move-branch: Use `git branch -f master HEAD~` if you're currently on another branch, or `git reset --soft HEAD~` if you're currently on master.
- Certhas 2y agoThe real "internal model" of git contains much more data/moving parts. There isn't one tree of commits, there are typically at least two: local and remote Branches are not just pointers to commits, but also possibly related to pointers in the other tree via tracking. Stash and index and the actual contents of the working directory are additional data that live outside the tree of commits. When op says "avoid git reset hard" it's because of how all these interact. Files can be tracked, untracked and ignored not ignored. All four combinations are possible.
- lalaithion 2y agoNone of these seem to preclude a command to make an arbitrary branch point to an arbitrary commit without changing anything else.
- fragmede 2y agoThis works if the branch exists or creates it if it doesn't exist, but not if it's checked out. git branch -f branch_name commit if it's checked out: git reset --hard commit
- seba_dos1 2y ago> but not if it's checked out ...and for a good reason that should be apparent to anyone who understands git's model (HEAD points to a ref in this case, so if you suddenly change what that ref points to without updating the working tree you create an inconsistency). You can do that manually of course (with `git update-ref` or even a text editor), but then you get to clean up the mess yourself.
- jimbokun 2y agoAre there alternative git command lines that keep the beautiful internals, but implement a more elegant and intuitive set of commands to manage it?
- dalia-reds 2y agoCheck out jujutsu or jj (same thing). It's its own VCS, but it uses git as a backend, so it works with GitHub and other git integrations
- stouset 2y agoSeconded jujutsu. It's 100% git-compatible and one of those rare birds that is both more powerful and simpler to use in practice due to rethinking some of the core ideas.
- maleldil 2y agoAnother vote for jujutsu. No one else needs to know you're using it. You can think of it as just a different CLI for git (although you shouldn't mix them). I used to use third-party interfaces like lazygit, but I don't need them anymore because jujutsu _just makes sense_.
- jonasced 2y agoLazygit has a terminal UI but might otherwise be what you're looking for: https://github.com/jesseduffield/lazygit https://github.com/jesseduffield/lazygit
- Terr_ 2y ago> The disconnect between git's beautiful internal model of blobs, a tree of commits, and pointers to commits, and the command line interface is so wild Something I heard somewhere that stuck with me: git is less less of a Version Control System, and more of a toolkit for assembling your own flavor of one.
- JadeNB 2y ago> Something I heard somewhere that stuck with me: git is less less of a Version Control System, and more of a toolkit for assembling your own flavor of one. That's how it is in principle, but it seems to me that there aren't that many different CLI "porcelains" in practice. Kind of like how Knuth figured people would essentially write their DSLs on top of plain TeX, not spend most of their time in giant macro packages like LaTeX.
- dragonwriter 2y ago> That's how it is in principle, but it seems to me that there aren't that many different CLI "porcelains" in practice. I think that's because most of the people that make custom tooling to support particular workflows build it into graphical (including IDE extensions, web-based. etc.) frontends, not CLIs.
- lilyball 2y agoThe "move a branch" command is `git push .`. Yes, you can push to the current repo. I have a script called git-update-branch which just does some preflight checks and then runs `git push --no-verify . +$branch@{upstream}:$branch` to reset a branch back to its upstream version.
- zahlman 2y ago> The "move a branch" command is `git push .`. Yes, you can push to the current repo. Wouldn't that copy a branch rather than moving it?
- lilyball 2y ago"move a branch" means changing the commit the branch points to. `git push . $sha:$branch` will update $branch to point to $sha (you'll probably want to force this, unless you're just fast-forwarding the branch).
- assbuttbuttass 2y ago> is there a command that simply moves a branch from one commit to another without changing anything else? It feels like it should be possible given how git works. git switch -C master HEAD~