CVS: Tracking all the changes in a branch - version-control

Say, I have three branches, Branch b0, b1 and b2.
b1 is forked some years back from b0 and b2 recently from b1.
All changes done on branch b2 are done by me and another developer, now what I need to do is to merge all my changes to branch b0.
I see two ways of doing it:
Manually copy-paste code (as code additions are quite independent) or
Create a diff file of Current state of branch b2 to the state where b2 was forked from b1. Apply the patch to b0, and manually handle conflicts.
2nd way seems more feasible to me, the only problem I have is how do I create a diff of all changes done on a branch?
Any other better way of doing this are also welcome.
Thanks,

Related

commit history after merging with tvfc

I have a branch B which is originated from branch A. I make 3 commits named c1, c2, c3 to branch A and then merge with branch B (using the wizard). But in source control explorer I don't seem to be able to see the 3 commits that I've made in B.
The history for branch A is:
c0 c4(merge with branch B)
^
|
|
here I expected to see c1, c2, c3
In git, we could see those using git log . How can I see them in tfvc? Are they there and just hidden or just doesn't care about those changesets.
Bottom line is I've seen pictures when there are tiny triangles on left side of each changeset in source control manager which shows the child branch commits on click. How can I have the same thing with TFVC?
thanks for your time.
-- I expected to be able to see all of the commits in branch B to be visible after merging in branch A.

git rebase interactive already pushed commits

Recently I had a lot of success rebasing a local-only repository while changing commit messages and after that only the commit messages had been changed but the history itself hasn't.
Now I have my repositories - remotely and locally. I made several commits on several branches and already pushed them. Due some reasons I need to change some commit massages over several branches and tried to use rebase interactive like before. But the commits appeared at the end of the current checked out branch.
(I know how to and I had reset my repositories to the state before rebasing.)
After some reading I realized the problem is the commits had been pushed already which wasn't the fact in my local-only repository.
I tried to rebase the remote repository, but it's a bare one - so it didn't work.
I know its not recommended. But for learning purposes I really like to know how to change several commit messages without resulting in duplicate commits at the end of my branch / repository.
(I don't like this solution: copy and to change my local repository to a bare one as my new remote repository, which would solve my problem.)
I hope I made myself clear enough. Thanks.
Changing the commit message results in changing the commit's hash value and this means all following commits have to change their hashes too (as the parent is included in the hash computation, as the message itself is too).
This is why rebasing is typically only allowed in local branches. Many or say most git remote repositories permit rewriting the pushed history as anyone could have downloaded it already and would then work on a outdated history/branch/commit.
Strategy for preventing or catching git history rewrite
However if your server does allow history rewrites (e.g. if you are the only one working on it) you may push them with --force.
As a side note see here https://stackoverflow.com/a/5668050/1756183
Edit rebase with several branches:
C1 <- C2 <- C3 (branch1)
rebasing children of C1 results in
C1 <- CR2 <- CR2 (branch1)
But if you have:
/ C4 <- C5 (branch2)
C1 <- C2 <- C3 (branch1)
rebasing will most likely lead to:
/ C2 <- C4 <- C5 (branch2)
C1 <- CR2 <- CR3 (branch1)
the reason is that C2 is still the parent of C4, the "fixed" commit CR2 is only related to the rewritten Branch branch1.
If you want to "forget" C2 you have to rebase C4 on top of CR2 (you ll have to play around with rebase --onto). After that C2 is not adressed as anyone's parent or on any branch and will not be shown in the history (although it is still there until garbage collected).

VCS theory - merge: recursive revrision merge or 3 revision merge?

I have a theoretical question about possible VCS merging.
I know that many VCS use 3 revision merge, which is common ancestor, "mine" and "your" revision. I know how they works.
I've thought about another alternative, recursive revision merge, haven't found this in Google.
"You found America!" you might think. I know Git use recursive merge.
But the reason Git is using recursive merge is for criss-cross merge
I'm talking about a normal case, non criss-cross merge.
For example, we have a common ancestor, A, and to branches, 1 and 2.
branch 1: B, C, D, E, F, G
branch 2: B', C', D', E', F', G'
As said before, A is the common ancestor so it's the parent of B and B'.
We want to merge G and G' into branch 1. The common way that Git and Mercurial use is the diff3:
diff3(ancestor = A, mine = G, yours = G')
This will compute merge by computing 3 version only, which is O(1).
The alternative algorithm I thought about is O(n):
merge the closest revisions to ancestor first.
merge the result with the next closest revision from branch 1
merge the result with the next closest revision from branch 2 (if remain)
repeat (in loop) to step 2 if there any revision in branch 1 remain.
In the above example it looks like:
merge B and B'
merge the result with C
merge the result with C'
merge the result with D
and so on...
The question I couldn't resolve is - Is there any case that my way is safer and more accurate (in non criss-cross merge) than the traditional 3 revision merge?
Can my way avoid conflicts that the traditional way cause?
Can my way create new conflicts that the tradition way doesn't cause?
Does my way conflicts are not "real" conflicts? (which the tradition way doesn't cause)
We want to merge G and G' into branch 1.
Why we want merge G into branch1? G is already in branch1. In best case we give nothing from this merge, in worst - conflict. Same for all other revisions without '
So only B' - G' need to be merged to branch1. And this is the 3-way merge.
BTW. third component of 3-way merge not 'common ancestor', but 'base'. Common ancestor can be base but not always.

Update branch from parent branch?

In CVS I have a branch (b) off another branch (a) which is off the trunk/head.
Some bug fixes were made in branch (a) that I'd like to go ahead and use in branch (b). How can I pull those fixes into my branch in Eclipse?
head
|
v
a (with bug fixes)
|
v
b (needs bug fixes)
Ideally what you need is to have two tags on a for every feature you want to merge, and then merge the difference between those two tags into b. However, you would also need to remember which ones you have already merged, because CVS doesn't remember that.
When I was working in a company that used CVS and branches, our policy was that bugfixes from branches (a in this case) that ought to be used by other branches need to get merged into the trunk first, and all the other branches merge them from there.
However, it was still very painful if you wanted to cherry-pick individual bugfixes. Essentially, you'd have to remember every fix you've merged (by two tags, marking the beginning and the end of the changes making up that fix).
Generally, in CVS it's much better to remember (in a tag) up to which revision you have merged, and merge everything from there to the head (and then move the tag to the head). In CVS, cherry-picking is painful and requires you to store the merge history somewhere.

Best practices to deal with "slightly different" branches of source code

This question is rather agnostic than related to a certain version control program.
Assume there is a source code tree under certain distributed version control. Let's call it A.
At some point somebody else clones it and gets its own copy. Let's call it B.
I'll call A and B branches, even if some version control tools have different definitions for branches (some might call A and B repositories).
Let's assume that branch A is the "main" branch. In the context of distributed version control this only means that branch A is modified much more actively and the owner of branch B periodically syncs (pulls) new updates from branch A.
Let's consider that a certain source file in branch B contains a class (again, it's also language agnostic). The owner of branch B considers that some class methods are more appropriate and groups them together by moving them inside the class body. Functionally nothing has changed - this is a very trivial refactoring of the code. But the change gets reflected in diffs. Now, assuming that this change from branch B will never get merged into branch A, the owner of branch B will always get this difference when pulling from branch A and merging into his own workspace. Even if there's only one such trivial change, the owner of branch B needs to resolve conflicts every time when pulling from branch A. As long as branches A and B are modified independently, more and more conflicts like this appear. What is the workaround for this situation? Which workflow should the owner of branch B follow to minimize the effort for periodically syncing with branch A?
The owner of branch B should have discussed the change with the owner of branch A. They should have decided that either the change was worth making, in which case it should have been committed to the trunk (A) or it wasn't, in which case it should have never been made. VCS is not a substitute for communication between developers.
Dev B should ask Dev A to pull from him.
The situation is not avoidable if two branches diverge and never converge. Its similar to a fork in a project - Its very difficult to merge two different forks.
Dev B should either un-refactor, or else add some meaningful functionality that has enough momentum to warrant merging back into A. Otherwise tell him "Them's the breaks".
To go to an extreme example, he could decide that he doesn't like C and decide to re-write everything as Pascal, line by line, using the same variable names, class names, etc.. To the point that the only difference is the language. So what would you tell him then, when he insists that there aren't any changes, so there should be no diff?
One workaround is to have a fancy diff wrapper around code comparison that will intelligently ignore certain very specific diffs.
On a simple level it's usually implemented via gdiff, on fancier, with custom diff code.
However, I must say that such a situation is really a bad thing and it's much better to merge the changes back into A; by for example submitting a patch to A's maintainers owners