While the explanation is right in some sense, it misses a few points. Branches are pointers to a commit and that pointer is refreshed when a new commit is created. One could say they are a wandering tag (without explaining a tag for now). The actual chain of commits that represent what we see as branch comes from the commits themselves. Those commits point back to their parent commit. And then one can see why no bran…
For years I was deeply annoyed by the terrible name “branch” for something that acts more like a bookmark (or “wandering tag” indeed!). And then I learned that git branches are branches in exactly the same way that the first element of a linked list in C “is” the linked list. Git was made by C people and they’re used to referring to entire data structures by way of some root element. I mean that doesn’t make me disli…
Git Branches: Intuition and Reality
121–130 of 281 posts
Re: Git Branches: Intuition and Reality
#122tl;dr Please ignore, just me working through a Python+pygit2 problem. I solved it in a grandchild comment. I had so much trouble trying to map my intuited/mental model of git onto pygit2 that I gave up and just used the git module. I wanted to automate a fairly simple thing in Python as opposed to bash+commands. My reasoning being that I wanted to do it "right" and be a Big Programmer Real Boy(tm). I just wanted to c…
This isn't asking someone else to make this work, it's more of a caution to convince folks like me to just use "import git" rather than pygit2: So something like this was what I expected to work, but leaves the repo in detached head state: import pygit2 def checkout_branch(path, branch_name): repo = pygit2.Repository(path) branch_ref = repo.lookup_reference(f"refs/remotes/origin/{branch_name}") print(f"{branch_ref.na…
There always seems to be just one more stackoverflow thread to read that has the real answer: https://stackoverflow.com/questions/68435607/how-to-clone-ma... (found via Kagi which I wasn't using before, and the search "pygit2 detached head")
def checkout_branch(path, branch_name):
repo = pygit2.Repository(path)
main_branch = repo.lookup_branch("main")
print(f"Main branch upstream: {main_branch.upstream_name}")
if branch_name not in repo.branches.local:
print(f"Branch {branch_name} not found in local branches")
remote_branch = "origin/" + branch_name
if remote_branch not in repo.branches.remote:
raise SystemExit(f"Branch {remote_branch} not found in remote branches")
(commit, remote_ref) = repo.resolve_refish(remote_branch)
repo.create_reference("refs/heads/" + branch_name, commit.hex)
branch = repo.lookup_branch(branch_name)
print(f"Branch name: {branch.name}")
repo.checkout(branch)
print(f"Is branch head? {branch.is_head()}")
(commit, branch_remote) = repo.resolve_refish("origin/" + branch_name)
print(f"Remote branch: {branch_remote.name}")
branch.upstream = branch_remote
With git reflog telling me the right thing: d44aedc (HEAD -> test, origin/test) HEAD@{0}: checkout: moving from main to test
And git push has the remote branch already set.I wish there was a pair programmer AI that you had to explain stuff to. That would enable the "by explaining it, I solved it" phenomenon.
Re: Git Branches: Intuition and Reality
#123Earlier quoted context omitted.
> moving files isn't stored in git is there an intuitive and enlightening explanation as to why it is this way?
For the historical rationale see here: https://gist.github.com/borekb/3a548596ffd27ad6d948854751756... In short, Linus stance is that file renaming doesn’t matter, only the contents of files matter, and the moving of contents between files. Moved/renamed files then fall out as a special case of moving content. Personally, I think this is a case of the better being the enemy of the good, and his “clearly superior algo…
Many people develop a bad mental model with commits as diffs, because that's what the UI makes them think commits are. It can work for a while, but inevitably leads to confusion later on.
Re: Git Branches: Intuition and Reality
#124Earlier quoted context omitted.
Possibly `git branch NEWBRANCHNAME` instead of `git checkout -b NEWBRANCHNAME`. When I need to show git to someone in order for them to contribute to something, I give them only these incantations --- and instructions to ask me if weird git things happen.
It's `git switch [-c]` nowadays.
git switch -c foo
git push
> did you mean git push --args-with-branch-name?
sigh, copy, paste, enterRe: Git Branches: Intuition and Reality
#125I don't use git at work, but in my private hobby projects my friends usually get mad when they watch me juggle changes and branch pointers with git reset --hard and git stash... How do you undo a merge that you didn't mean to do/did wrongly? git reset --hard Have some cosmetic fixups on your local branch that really should go into main (or a separate branch) first before merging a bigger feature? git stash git checko…
Your strategy of seeing things as they are is a useful general purpose life skill.
Re: Git Branches: Intuition and Reality
#126Re: Git Branches: Intuition and Reality
#127for example: git merge my-branch will merge my-branch into the current one
while git rebase my-branch will rebase current one on top of my-branch
Re: Git Branches: Intuition and Reality
#128Earlier quoted context omitted.
For years I was deeply annoyed by the terrible name “branch” for something that acts more like a bookmark (or “wandering tag” indeed!). And then I learned that git branches are branches in exactly the same way that the first element of a linked list in C “is” the linked list. Git was made by C people and they’re used to referring to entire data structures by way of some root element. I mean that doesn’t make me disli…
When the entire structure of commits is called a tree, I find the name "branch" fitting. The branch is identified by its head commit, so the path from head to root is uniquely defined and that's the branch. (Disregarding merges for now.)
Without disregarding them, it's not a tree, but a DAG.
Re: Git Branches: Intuition and Reality
#129Earlier quoted context omitted.
For the historical rationale see here: https://gist.github.com/borekb/3a548596ffd27ad6d948854751756... In short, Linus stance is that file renaming doesn’t matter, only the contents of files matter, and the moving of contents between files. Moved/renamed files then fall out as a special case of moving content. Personally, I think this is a case of the better being the enemy of the good, and his “clearly superior algo…
I don't think it's about having a stance, it's about git's architecture. From the commit graph point of view, there's no such things as moving anything at all, neither files nor content. Commits represent a whole new state of the repository, not a diff from the previous state. The only way a commit is linked to the previous state is via parent pointer, it can otherwise be completely unrelated (and you can simply chan…
Viewing the commit graph in terms of nodes (commits) or edges (diffs) is equivalent, these are dual views you can easily convert between. The internal representation is independent from that. Some VCSs use a mix of diffs and full revisions internally. Even Git uses delta compression when packing objects.
Re: Git Branches: Intuition and Reality
#130While the explanation is right in some sense, it misses a few points. Branches are pointers to a commit and that pointer is refreshed when a new commit is created. One could say they are a wandering tag (without explaining a tag for now). The actual chain of commits that represent what we see as branch comes from the commits themselves. Those commits point back to their parent commit. And then one can see why no bran…
For years I was deeply annoyed by the terrible name “branch” for something that acts more like a bookmark (or “wandering tag” indeed!). And then I learned that git branches are branches in exactly the same way that the first element of a linked list in C “is” the linked list. Git was made by C people and they’re used to referring to entire data structures by way of some root element. I mean that doesn’t make me disli…
FWIW this is actually backwards. The word "branch" was already in common use (to refer to the same basic idea) in SCM systems going back decades, and in almost all of those a "branch" was indeed a first class object with its own data that acted as a "container" for commits, both semantically and physically.
The fact that a "branch" is just a pointer is in fact a git innovation on top of the former idea.