mackyle / topgit

TopGit - A different patch queue manager
https://repo.or.cz/topgit/pro.git
Other
67 stars 7 forks source link

two questions on topgit workflow and [BASE] branches #11

Closed ede-extern closed 3 years ago

ede-extern commented 5 years ago

We are following an upstream repo (that we don't maintain, of course) with our clone and would manage our patches with topgit. For a complete minimal example see the bash commands below.

Our first, general question: is this the "correct" workflow or are we missing something? The topgit manual is very detailed regarding the individual commands, but we couldn't find something like a "big picture" or "recipes" for typical usage.

The second question is: what is the whole purpose of [BASE] branches (as recommended in #7 )? It is fine for creating topic branches and the release branch on a plain code base. But as you can see in the last three lines, after updating the [BASE] branch to a new release, it is gone from topgit. To continue work after this release we would have to create a new [BASE] branch (with a different name, because mybase still exists in plain git). From the example given in the tg create man page we would think that the release branch used there still "lives" after v2.1 and v2.2.

bash commands for our test:

# create upstream repo with a version U1.0
git init upstream
cd upstream/
echo "README for upstream" > README
echo "/* tiny c file */" > tiny.c
echo "/* tiny h file */" > tiny.h
git add .
git commit -m "initial checkin of upstream"
git tag "U1.0"
cd ..

# clone upstream, init tg and create two topic branches
git clone upstream tgtest
cd tgtest/
git checkout -b mymaster U1.0
tg create --base --topmsg "create my tg base" mybase
tg tag -m "tg-base-tag-as-recommended" tg-base-tag-as-recommended --all
#tg checkout mybase
tg create --topmsg "create t/feat1" t/feat1
echo "/* reformat to my conventions */" >> tiny.c
git commit -am "reformat to my conventions"
tg checkout mybase
tg create --topmsg "create t/feat2" t/feat2
echo "/* reformat to my conventions */" >> tiny.h
git commit -am "reformat to my conventions"

# create a release S1.0 including the two features
tg checkout mybase
tg create --topmsg "create release" release t/feat1 t/feat2
tg tag -m "create tag S1.0" S1.0

# update the [BASE] branch and it is gone
tg summary
tg update --base -m "try to tg update --base" mybase S1.0
tg summary
mackyle commented 5 years ago

Using the tg summary --rdeps command you can see a dependency graph of your TopGit branches:

release
  t/feat1
    mybase
  t/feat2
    mybase

Make sense? t/feat1 is built on top of mybase (similarly for t/feat2) and then release is built from both of the features.

Initially mybase is pointing at the same commit as U1.0.

You built the two feature branches (t/feat1 and t/feat2) on top of it where each of those branches represents a single "logical patch" to TopGit.

TopGit considers the patch to be the difference between the TopGit branch's base and the tip of that TopGit branch.

The tg patch t/feat1 and tg patch t/feat2 commands will show you what TopGit thinks the "logical patch" is for each of those two branches.

The tg base t/feat1 and tg base t/feat2 commands will show you what commit TopGit is using for each of those branches when computing its "logical patch".

To more easily see the entire Git commit graph you might try:

git log --oneline --graph --decorate --all

Then there's this sequence:

tg tag -m "create tag S1.0" S1.0 release
tg update --base -m "try to tg update --base" mybase S1.0

The tg update --base told TopGit to move the mybase branch from pointing at the same commit as U1.0 to now pointing at the same commit as S1.0 and then merge all those changes up through the TopGit dependency graph.

Look again at the --rdeps output above. The values output by tg base t/feat1 and tg base t/feat2 will be changed after the tg update --base and as a result the base of each of the TopGit branches has the changes from the freshly updated mybase branch merged into it so each of the feature branches no longer introduces any new changes of their own compared to their base which is why everything seems to go away.

Look at this simplified example:

A -- B -- C -- D

Where initially mybase points at A and t/feat1 points at D.

The patch is just the diff from A to D. Now D is tagged as the release and mybase is updated to point to it (which is essentially what those last two commands above did). The patch is now the diff from D to D which is nothing.

The intent of the tg update --base functionality is that once upstream releases a U2.0 for example, you come along and run this:

tg update --base -m "move patches to U2.0" mybase U2.0

And now your release staging branch has all the patches built up on top of U2.0 instead of U1.0.

If you want to tag the staging branch before you run the base update you can do that using a normal git tag command. You only need to use tg tag command if you might want to use the TopGit -w option or the TopGit tg revert command at some point in the future.

ede-extern commented 5 years ago

thanks for your exhaustive answer. With your explanations i found the problem: i was using a tg tag in the update command. Initially my last three lines give:

$ tg summary
 0       mybase                         [BASE] create my tg base
>0       release                        [PATCH] create release
         t/feat1                        [PATCH] create t/feat1
         t/feat2                        [PATCH] create t/feat2
$ tg update --base -m "try to tg update --base" mybase S1.0
Merge made by the 'recursive' strategy.
$ tg summary
>0       release                        [PATCH] create release
         t/feat1                        [PATCH] create t/feat1
         t/feat2                        [PATCH] create t/feat2

That is what i meant with "the [BASE] branch is gone". The important thing to know is, that the <ref> argument must be an upstream (i.e. non-tg) tag:

$ tg summary
 0       mybase                         [BASE] create my tg base
>0       release                        [PATCH] create release
         t/feat1                        [PATCH] create t/feat1
         t/feat2                        [PATCH] create t/feat2
$ tg update --base -m "try to tg update --base" mybase U1.0   # not useful here, but shows the point
No change
$ tg summary
 0       mybase                         [BASE] create my tg base
>0       release                        [PATCH] create release
         t/feat1                        [PATCH] create t/feat1
         t/feat2                        [PATCH] create t/feat2

When using tags not maintained by tg, the tg update --base works like a charm. This issue can be closed then.

mackyle commented 5 years ago

I think there might be a bug here...

I'd like to play with it a little bit more but I want to make sure I'm using the same versions you are. Could you please report the output of:

tg version

and

git version

Thanks.

Also the mybase branch isn't really gone. You should be able to see it with this:

tg summary -vvl

(That's short for --verbose --verbose --list) Or with:

tg info mybase

I suspect it ends up having a tip and base with the same tree after the merge which is why it doesn't normally show up.

ede-extern commented 5 years ago

No problem. The machine is a VM with Ubuntu 16.04.5 LTS. The commands give:

$ tg version
TopGit version 0.19.11-5-g4656
$ git version
git version 2.7.4
$ tg summary -vvl
mybase                                  branch mybase (annihilated)
release                                 [PATCH] create release
t/feat1                                 [PATCH] create t/feat1
t/feat2                                 [PATCH] create t/feat2
$ tg info mybase
Topic Branch: mybase (1/0 commit)
Subject: branch mybase (annihilated)
Base: 4c2a4fb
Up-to-date.
mackyle commented 5 years ago

thanks. sure looks like a bug to me. using it the way you did was not envisioned, but still it's not supposed to do what it did (zap out the .topmsg and .topdeps files). The code that prevents that exact thing from happening needs to be factored out for use in other places as well, so when that happens this should get corrected. In the meanwhile I'll be adding an expect-fail test so this doesn't get lost.

mackyle commented 3 years ago

The necessary code refactoring finally has been completed and with the release of topgit-0.19.13 this bug has been squashed. There's even a new test in t5002 to make sure this continues to work properly.

What will happen if you do this now (including the tg update) and run a plain tg summary afterwards, all your branches will be there and they will all show a "0" as they will all then have no changes, but none of them will disappear.