Can I use the same branch instead of a new branch?

I develop on the development branch. Normally I then create my feature branches from the development branch. Like scenario 1:

Scenario 1

development -> featureA -> development -> megre featureA = COMPLETE 
// A few feature branches later I realise I need to do something in featureA 
development -> featureA_1 -> development -> megre featureA_1 = COMPLETE 

But I also thought I could take the already existing featureA branch and bring it up to date. Like in scenario 2.

Scenario 2

development -> featureA -> development -> megre featureA = COMPLETE 

// A few feature branches later I realise that I still have to do something in featureA 
develompment -> featureA 
-> merge development 
-> ..add new things ... 
-> development 
-> merge featureA_1

Question: Can scenario B cause problems?


Solution 1:

It's important to realize that to Git, branches—or really, branch names—are irrelevant and unimportant. What matters in Git are the commits. It's possible to use Git without using any branch names at all: it's just extremely inconvenient for humans to work this way.

Git finds commits by hash IDs. The hash ID of a commit is, in effect, its "true name": see the Wikipedia definition and, if you don't mind getting lost in the TV-Tropes pages, the TV trope "I Know Your True Name". But hash IDs are large and ugly and impossible for humans to remember: can you tell dcc0cd074f0c639a0df20461a301af6d45bd582e from dcc0a86f2f2f036b3a379f41a4b754f8bb73ed6b, at a glance? But if one of these is master right now, and one was master or some other name some time in the past, well, those are meaningful to humans. So we use branch names.

A branch name, in Git, is a name with several particular properties. All references in Git store one hash ID, so a branch name stores one hash ID. What makes a branch name special is:

  • its full name starts with refs/heads/: dev is short for refs/heads/dev, for instance;
  • Git will allow you to be "on" a branch name: other names force what Git calls detached HEAD mode, requiring the --detach flag when using git switch and automatically detaching when using git checkout; and
  • when you make a new commit and are "on" some branch, Git will automatically write the new commit's hash ID into the branch name.

It is this last property that makes branch names particularly useful: after git checkout branch or git switch branch, we're "on" that branch, and new commits automatically advance the branch name. Without this feature, we'd be stuck writing down all our commit hash IDs just to be able to find them again, or something equally obnoxious (manual git update-ref of each name as we work, perhaps).

In any case, once you realize that the purpose of a branch name is simply to be able to find commits, many things that were mysterious about Git before, become much simpler. If you visualize your repository as commits—connected with one-way, backwards-pointing arrows, so that each "child" commit remembers its parent or parents—you get a simple Directed Acyclic Graph like this:

          D <-E <-F
         /
A <-B <-C
         \
          G <-H

where F and H are the latest commits in two "branches" that comes together, or split apart, at commit C, depending on whether you traverse your commits "backwards" (Git-style) or "forwards" (human-style). Branch names simply locate specific commits:

        D--E--F   <-- br1
       /
A--B--C   <-- main
       \
        G--H   <-- br2

for instance, or maybe:

        D--E--F   <-- develop
       /
A--B--C--G--H   <-- master

Note that these are the same graph. The fact that one graph has a name for commit C, and one doesn't, does not affect the graph. Since Git is all about the commits and the graph—and not at all about branch names—these are basically the same repository, in terms of what Git would do anyway. All we have to to to change the second one into the first is rename develop to br1, rename master to br2, and add a name main pointing to commit C.

That's probably not how humans will intend to use this, but that's what Git sees. So questions like this:

Can scenario B cause problems?

are really questions about whether humans will make certain mistakes. I don't think anyone can really predict human reliability properly, but if you know what kind of mistakes you personally make, you might be able to assess what will work best for you specifically. That's not really a technical issue of the kind one can solve by grabbing a StackOverflow answer, though. 😀