Ehsan Ali
Ehsan Ali

Reputation: 1432

Best Approach for GIT log graph with separate and individual line for every branch

I wanna to use git-flow as workflow in git. But I have problem with see git log --graph. For example I have four branch:

 -master-    -develop-    -feature/sms-    -release/v1.0
    |            |             |                 |

I want to see every branch in separate and individual like blow image: git graph

What should I do? or Which tool is good for my need?

Upvotes: 1

Views: 376

Answers (1)

torek
torek

Reputation: 487993

You literally cannot do this in general. You can fake it up for specific cases, which might be good enough for you; but you will have to do this yourself, because Git will not.

The reason for this is simple: the graph you show is a lie. It tries to pretend that Git works forwards. Git does not: Git works backwards.

In Git, commits are not, in general, on a single branch. Instead, commits are on many branches simultaneously. Here is a textual representation of that same graph:

master:    A--B-----------------------P--...
               \                     /
release:        \                K--M
                 \              /    \
develop:          C-----F------I------R--...
                   \     \    /
feature1:           D--E-----H
                           \
feature2:                   G--J--L--N--...

This, too, is a lie: it implies that commit A, for instance, is only on master. In fact, commit A is on every branch.

Since there are ... parts that we cannot see, it is hard to say for certain whether commits G-J-L-N-... are on more than one branch: we need to start at the end, like Git does, to see reality instead of a lie. We can say, though, that these commits are definitely on feature2 right now. Meanwhile, commits C and F are on both feature2 and develop. The only branch we cannot be sure contains the D-E-H sequence is feature2: all four of those commits are definitely on feature1, but also definitely on develop, because I is on develop and I reaches back to H. Meanwhile commit K is on release, but since K reaches back to I, I is also on release; since I tracks back to both F and H, those two commits are also on release.

In short, the problem here is that we are attempting to work forwards. Git does not work forwards. Git works backwards, starting from the last commit on a branch. Let's assume that we do in fact have these last commits, and re-draw everything:

A--B-----------------------P   <-- master
    \                     /
     \                K--M
      \              /    \
       C-----F------I------R   <-- develop
        \     \    /
         D--E-----H
                \
                 G--J--L--N   <-- feature2

This drawing is truthful, rather than a lie (well, presumably, for some repository at some time).

The three names I added here are the only names that we need to retain all the commits shown, because they are the only three last commits. We can add another name, such as feature1, pointing to, say, commit H, and more names as we like:

A--B-----------------------P   <-- master
    \                     /
     \                K--M   <-- release
      \              /    \
       C-----F------I------R   <-- develop
        \     \    /
         D--E-----H   <-- feature1
                \
                 G--J--L--N   <-- feature2

This last graph is a (not necessarily the, but a) truthful way to draw things. The name release identifies commit M, and from M, we—and Git—can work backwards to find commit K, then continue back from K to I, and on to both F and H simultaneously. Then from F and H we can work back to C and E simultaneously, and to D (which also goes back to C); and from C we can walk back to B and then to A. So commits A-B-C-D-E-F-H-I-K-M are all reachable from release.

If we delete the name release, nothing happens to the commits. The commits are all still there. They just are no longer contained in the release branch, which no longer exists. They are still contained in master, because master starts at—ends at?—P, which works backwards to both M and B. Since P reaches M, every commit reachable from M is also reachable from P.

If you think of this as driving down a one-way street, in a network of one-way streets, you're on the path to enlightenment. For (much) more about this, I recommend working through the web site Think Like (a) Git. Pay close attention to the idea that what you want is to have your tools hide (some) commits from you (on the Making Sense of the Display page).

Note that there are other version control systems that work the way you would like Git to work. Mercurial, in particular, is very similar to Git, except that commits are on the branch they are made on, forever. Each commit is only on one branch. The commit that contains a branch remains the same, regardless of what you do with your branch names. In Git, because the names move while the commits remain unchanged, the set of branches that contains any given commit changes all the time! If you are not prepared to have this happen to you in Git, you will be miserable when using Git.

Upvotes: 3

Related Questions