Files
DIY_GIT_in_Python/how_to/Change_30.md

3.1 KiB
Raw Blame History

  • branch: Create new branch

Tags were an improvement since they freed us from the burden of remembering OIDs directly. But they are still somewhat inconvenient, since they are static. Let me illustrate:

o-----o-----o-----o-----o-----o-----o
                   \                ^
                    ----o-----o  tag2,HEAD
                              ^
                           tag1

If we have the above situation, we can easily flip between tag1 and tag2 with checkout. But what happens if we do

- ugit checkout tag2
- Make some changes
- ugit commit?

Now it looks like this:

o-----o-----o-----o-----o-----o-----o-----o
                   \                ^     ^
                    ----o-----o  tag2     HEAD
                              ^
                           tag1

The upper branch has advanced, but tag2 still points to the previous commit. This is by design, since tags are supposed to just name a specific OID. So if we want to remember the new HEAD position we need to create another tag.

But now lets create a ref that will “move forward” as the branch grows. Just like we have ugit tag, well create ugit branch that will point a branch to a specific OID. This time the ref will be created under refs/heads.

At this stage, branch doesnt look any different from tag (the only difference is that the branch is created under refs/heads rather than refs/tags). But the magic will happen once we try to checkout a branch.

So far when we checkout anything we update HEAD to point to the OID that weve just checked out. But if we checkout a branch by name, well do something different, we will update HEAD to point to the name of the branch! Assume that we have a branch here:

o-----o-----o-----o-----o-----o-----o
                   \                ^
                    ----o-----o tag2,branch2
                              ^
                           tag1

Running ugit checkout branch2 will create the following situation:

o-----o-----o-----o-----o-----o-----o
                   \                ^
                    ----o-----o tag2,branch2 <--- HEAD
                              ^
                           tag1

You see? HEAD points to branch2 rather than the OID of the commit directly. Now if we create another commit, ugit will update HEAD to point to the latest commit (just like it does every time) but as a side effect it will also update branch2 to point to the latest commit.

o-----o-----o-----o-----o-----o-----o-----o
                   \                ^     ^
                    ----o-----o  tag2     branch2 <--- HEAD
                              ^
                           tag1

This way, if we checkout a branch and create some commits on top of it, the ref will always point to the latest commit.

But right now HEAD (or any ref for that matter) may only point to an OID. It cant point to another ref, like I described above. So our next step would be to implement this concept. To mirror Gits terminology, we will call a ref that points to another ref a “symbolic ref”. Please see the next change for an implementation of symbolic refs.