This is my workflow
I have a branch that needs to get update.
So before working i do hg sync and that syncs with p4head but creates a new branch .
So once I do hg xl I see something like
#xxxxxx bugid: working changes(A)
|
|
|
|. xxxxx:bugidworking changes(c)
| /
| xxxxxx bugid:working changes(b)
o /
What I want to do is eliminate b and c but keep a
Is there a dry run that I can test?
Related
Here is what I am trying to do. I have a commit to the default branch that I need off default. We build for production from default and this commit is not ready. So I have used hg backout to undo the changes from the default branch. Now I have created a new branch to store the changes. But when I attempt to transplant or graft the changes onto the branch I get told that I cannot graft in changes from an ancestor. This makes sense, but I need to pull changes from an ancestor, how do I do this.
I have tried
hg diff -c 8c13fc133926 > new_branch.diff
hg import new_branch.diff
but this Fails with no explanation. Any pointers?
EDIT
It seems I'm a little hard to follow, so I will try and clarify.
o Default with only ready changes
|
| o Not ready changes (new commit on a branch)
| |
|/
o Hg backout commit Undoing not ready changes from default
|
o Lots of other commits and merges to default
|
o ...
|
o Not ready changes (original commit)
The graph above shows where I need to get to.
I have done this by using hg diff -c 6877 | patch -p1 where 6877 is the revision of the commit that needs to be moved off of default.
But I think I am doing this wrong.
Make your new branch off of the revision BEFORE you made the "not ready changes" commit. I will call that revision 123:
hg up 123
hg branch NewBranch
hg ci -m "branching for NewBranch"
Now you can do your GRAFT, with no concerns about ancestors.
Tying up loose ends:
It seems that you'll already have another head on NewBranch, the one you said you created. You can merge with that or just close it. You can see the heads with:
hg heads NewBranch
I will call that unwanted head revision 456. And I would close it like this:
hg up 456
hg ci --close-branch -m "It was all just a dream... a terrible, terrible dream."
Which reminds me: you could have used the same technique (closing an unwanted branch head) instead of hg backout! Then you could have done the steps above ... except you'd be able to do a neat-and-tidy REBASE ("leaving no witnesses", like they say in the movies) instead of cherry-picking with GRAFT, and leaving behind the wreckage on the default branch!
I personally avoid grafting as much as possible, and your commit is already in the history. You seem to be using the correct commands, but it is hard to understand your issue, more information is needed.
How about creating your new branch from the commit that you wanted to backout?
o NewBranch: head, creation of the branch
|
|
o | default: head, Backed-out changeset
| |
|/
o default: commit (not ready)
|
|
o default: initial state
|
Another idea, if you don't care about grafting, simply start your new branch from the initial state, and transplant the commit; it won't be considered an ancestor anymore.
o NewBranch: head, grafted commit
|
/|
| o NewBranch: creation
| |
| |
o | | default: Backed-out changeset
| | |
|/ |
o / default: commit (not ready)
| /
|/
o default: initial state
|
Using Mercurial. Working in private clones, making changes, pushing to master. Etc. That's fine.
(By the way, let me state that I am familiar with many version control systems ranging from the classics SCCS, RCS, CVS, SVN to DVCSs like BitKeeper, Git, Mercurial, passingly familiar with Monotone, Darcs, Bzr. Not so familiar with Perforce, ... I just mention this for people who may be able to explain equivalents and similarities between systems.)
Unfortunately, other members of the project think that I check in too often. I use the "check in early and often" approach, sometimes checking in more often than once every half hour. They don't want to see so many checkin messages in the log.
NOT QUESTION: Now, I have taken to the habit of making most of my changes on branches (although hg lacks retroactive branching), summarizing all of the changes when I merge my task branches back to the trunk. hg log -b default allows them to filter out my task branches, and works okay when the merge messages are meaningful. This is not my question.
NOT QUESTION: similarly, I know how to use history editing, etc., to remove my fine granularity changesets, so that the only changesets that get pushed are coarse grain. (Although, by the way, I often find the simplest thing to do is move .hg directories around.) History editing ias annoying, but I can do it.
MY QUESTION: my question is: I would like to keep track of my fine granularity changesets and log messages, even though I don't push them to the project master repository.
Q: how do I do this?
I.e. how do I keep two repositories tracking each other, but NOT push all of my changes to the master? Preferably tag changesrts not to be pushed. (By the way, I prefer to say "tag a revision set". Changeset sounds too much like patch.)
The way I do it now is to have
a) the project master repo
b) my personal master repo, with all of the fine grain changes
c) one or more workspaces
Where
a) clone the project master repo to get the workspace (using hg clone, yyeah, I know)
b) work in the workspace clone with fine grain checkins (I know this)
c) push from the workspace clone to my personal master
d) and, when it comes time to push to the master, edit the history, and push that.
Two troubles:
1) conflicts merging or pushing from the workspace clone to my personal master
- more precisely, conflicts when merging from the master repo with history edited to remove the fine grain checkins, to my personal master with the fine grain checkins preserved.
2) I would like to record what has been pushed to the project master in my personal master.
--
A very simple example.
A task branch, with fine grain checkins.
o changeset: 1022:
| branch: default
| parent: 1017
| parent: 1021
| summary: Merged task branch onto main, default, branch, with changes to FOO and BAR
|
o changeset: 1021
|\ branch: task-branch
| | parent: 1020
| | summary: Merged default branch to task-branch, with changes to FOO and BAR
| |
| o changeset: 1020
| | branch: task-branch
| | parent: 1018:
| | summary: yet another fine grain checkin on a branch changing BAR for a second time
| |
o | changeset: 1019
| | branch: task-branch
| | parent: 1018:
| | summary: yet another fine grain checkin on a branch changing FOO
| |
o | changeset: 1018
| | branch: task-branch
| | parent: 1017
| | summary: yet another fine grain checkin on a branch changing BAR a first time
| |
|/
o changeset: 1017
| branch: default
| summary: some other changeset on the default branch, i.e. trunk
|
The edited history, that gets pushed to the project master
o changeset: 1018: ...changed checksumm because checksum seems to include history
| branch: default
| parent: 1017
| summary: Merged task-branch onto main, default, branch, with changes to FOO and BAR.
| Removed task-branch-history from what got pushed to project repo,
| although may still be in personal repo
|
o changeset: 1017
| branch: default
| summary: some other changeset on the default branch, i.e. trunk
|
The problem is, when I try to merge an updated projecvt master, that may look like
o changeset: 1019
| branch: default
| parent: 1018
| summary: again, some other changeset on the default branch, i.e. trunk
|
o changeset: 1018: ...changed checksumm because checksum seems to include history
| branch: default
| parent: 1017
| summary: Merged task-branch onto main, default, branch, with changes to FOO and BAR.
| Removed task-branch-history from what got pushed to project repo, ]
| although may still be in personal repo
|
o changeset: 1017
| branch: default
| summary: some other changeset on the default branch, i.e. trunk
|
I get conflicts, even though changeset 1018 of the project master and 1022 in the personal master are exactly the same, in terms of file contents.
I've tried not changing the comments in the merge changesrt that gets pushed. Doesn't help, at least not reliably.
I wonder if the full history is included in the changesets.
I also wonder if there is some merge tool that can recognize same files, even though different history and log messages.
In general any workflow that involves editing history is not going to work well. It's just not the intended work mode, and no effort goes into making it work well.
Better options for you might be:
Versioned Mercurial Queues (hg qinit --create-repo) which lets you make multiple commits iterating on a single patch. You get the full history in your private patch repo and they only get the qfinished whole.
Rather than merge back your task branch and edit history, just re-apply the change as a single commit and push that. In your example it would be hg diff -r 1017 -r 1021 | hg import, which creates a new commit (1022) that is the sum of all the changes 1018::1021, inclusive. that should merge cleanly and be pushable without ever having to push any changesets on your task-branch out to them. You can even hg commit --close-branch on the task branch
Tell your coworkers to STFU. ;) High changeset granularity is good practice, and they should adapt.
Also, consider using bookmarks instead of named branches for your task-branches. Similarly the new phases feature makes it possible to mark changesets in your task branches (be they bookmark-branches or old-style named-branches) as secret so they can't be accidentally pushed.
I created a new repository, test-backout, and added a new file in it, file. I then made 4 commits, each time, appending the number of the commit to file using
echo [manually entered number] >> file
hg commit -m '[manually entered number]'
In effect, file had:
init
1
2
3
According to the hg book, if I run hg backout --merge 2, I should have:
init
1
3
but instead, it fails to merge and opens up my difftool (vimdiff), and I get 3 options:
init | init | init
1 | 1 |
2 | |
3 | |
I initially tried it with the --merge option, then again without it. My question now is, is there still a way for me to get:
init
1
3
did I just make a mistake or miss something, or am I stuck with those options?
A big factor in why you got the 3-way merge is that your context is too artificial, and I will get to that.
If I take a 50-line text file and change a different part and commit each change, I won't have to resolve conflicts. And what I mean is I have 4 changesets: rev 0 adds the file, revs 1, 2, and 3 each change one area of the file: the beginning, middle, or end.
In this situation, when I do hg backout 2, it makes a reverse of rev 2 and merges those changes to my working directory, and when I commit, the graph is linear:
# backout 2
|
o 3
|
o 2
|
o 1
|
o initial
If I instead do hg backout 2 --merge, it automatically commits the backout as a child of the revision it is backing out, and then merges that with the tip, producing a branched graph after I commit the merge:
# merge
|\
| o backout 2
| |
o | 3
|/
o 2
|
o 1
|
o initial
In both situations, I didn't have to do any 3-way merging. The reason you don't automatically get
init
1
3
and instead have to do a 3-way merge is that the changes are too close together. The context and changes in each changeset are completely overlapped (default number of lines of context for a diff chunk is 3 lines, which encompasses the entire file still in your 4th changeset).
A similar example is if you had 3 changesets that each modified the same line. If you backed out the middle change like you're doing here, you would still be presented with a 3-way merge that you'll likely have to manually edit to get correct.
By the way, behavior did change in 1.7, as attested by hg help backout:
Before version 1.7, the behavior without --merge was equivalent to specifying --merge followed by "hg update --clean ." to cancel the merge and leave the child of REV as a head to be merged separately.
However, I don't think that's quite what you suspected.
I recently tried to merge a series of changeset and encountered a huge number of merging issues. Hence I'd like to to try to apply each changeset, in order, one by one, in order to make the merging issues easier to manage.
I'll give an example with 4 problematic changesets (514,515,516 and 517) [in my real case, I've got a bit more than that]
o changeset: 517
|
o changeset: 516
|
o changeset: 515
|
o changeset: 514
|
|
| # changeset: 513
| |
| o changeset: 512
| |
| o
| |
| o
| |
| o
|/
|
|
o changeset 508
Note that I've got clones of my repos before pulling the problematic changesets.
When I pull the 4 changesets and try a merge, things are too complicated to resolve.
So I wanted to pull only changeset 514, then merge. Then once I solve the merging issue, pull only changeset 515 and apply it, etc. (I know the numbering shall change, this is not my problem here).
How am I supposed to do that, preferably without using any extension? (because I'd like to understand Mercurial and what I'm doing better).
Is the way to go generate a patch between 508 and 514 and apply that patch? (if so, how would I generate that patch)
Answers including concrete command-line example(s) most welcome :)
I haven't tested this, but merging individual changesets should be easy enough:
$ hg update -r 513
$ hg merge -r 514
... # do your conflict resolution and commit
$ hg merge -r 515
... # repeat
I haven't tested either, but it should work to just hg up to each of the foreign changesets one after the other. I don't think you have to commit between the updates.
As a bonus, the command line example you wished :-)
hg up 513
hg up 514
hg up 515
hg up 516
hg up 517
I've been doing some development on a branch and realized that before it could be complete something else need to be done first. I decided that I would branch my current branch and do the requiste changes in that branch then merge them back together and then merge my working branch into default. Basically I expected this:
| | + requiste work branch commit.
| |/
| + working branch commit
|/
+Default branch commit
and in the end what I expect to do is this:
+ Merge into defualt
|\
| + Merge requisite work into working branch
| | \
| | + requiste work branch commit.
| |/
| + working branch commit
|/
+Default branch commit
What I'm getting in both hg view and hg serve is this:
| + requiste work branch commit.
| |
| + working branch commit
|/
+Default branch commit
However, when I look at the commit log "requiste work branch commit" is marked as a part of a different branch.
Am I doing something wrong? Is this a bug in hg view and hg serve? Anyone experienced this before?
If there are no further commits on the first branch after "working branch commit" (except on the second branch), then the view may appear as a straight line (which is what you are seeing). I suspect that the reason for this is merely an optimization in the display code. As soon as you make another commit to the first branch, it should display the way that you are expecting.
The missing link here is that there is no commit on which is a child of "working branch commit" and not on the same branch as "requisite work branch commit". Thus, as one is a child of the other and there's nothing to show in a third column, you only see two columns. For the same reason, merging "req..." with "working..." is currently meaningless.