Show More
@@ -3054,6 +3054,7 b' def forget(ui, repo, *pats, **opts):' | |||||
3054 | ('c', 'continue', False, _('resume interrupted graft')), |
|
3054 | ('c', 'continue', False, _('resume interrupted graft')), | |
3055 | ('e', 'edit', False, _('invoke editor on commit messages')), |
|
3055 | ('e', 'edit', False, _('invoke editor on commit messages')), | |
3056 | ('', 'log', None, _('append graft info to log message')), |
|
3056 | ('', 'log', None, _('append graft info to log message')), | |
|
3057 | ('f', 'force', False, _('force graft')), | |||
3057 | ('D', 'currentdate', False, |
|
3058 | ('D', 'currentdate', False, | |
3058 | _('record the current date as commit date')), |
|
3059 | _('record the current date as commit date')), | |
3059 | ('U', 'currentuser', False, |
|
3060 | ('U', 'currentuser', False, | |
@@ -3077,6 +3078,10 b' def graft(ui, repo, *revs, **opts):' | |||||
3077 |
|
3078 | |||
3078 | (grafted from CHANGESETHASH) |
|
3079 | (grafted from CHANGESETHASH) | |
3079 |
|
3080 | |||
|
3081 | If --force is specified, revisions will be grafted even if they | |||
|
3082 | are already ancestors of or have been grafted to the destination. | |||
|
3083 | This is useful when the revisions have since been backed out. | |||
|
3084 | ||||
3080 | If a graft merge results in conflicts, the graft process is |
|
3085 | If a graft merge results in conflicts, the graft process is | |
3081 | interrupted so that the current merge can be manually resolved. |
|
3086 | interrupted so that the current merge can be manually resolved. | |
3082 | Once all conflicts are addressed, the graft process can be |
|
3087 | Once all conflicts are addressed, the graft process can be | |
@@ -3151,51 +3156,52 b' def graft(ui, repo, *revs, **opts):' | |||||
3151 | return -1 |
|
3156 | return -1 | |
3152 |
|
3157 | |||
3153 | # check for ancestors of dest branch |
|
3158 | # check for ancestors of dest branch | |
3154 | crev = repo['.'].rev() |
|
3159 | if not opts.get('force'): | |
3155 | ancestors = repo.changelog.ancestors([crev], inclusive=True) |
|
3160 | crev = repo['.'].rev() | |
3156 | # Cannot use x.remove(y) on smart set, this has to be a list. |
|
3161 | ancestors = repo.changelog.ancestors([crev], inclusive=True) | |
3157 | # XXX make this lazy in the future |
|
3162 | # Cannot use x.remove(y) on smart set, this has to be a list. | |
3158 | revs = list(revs) |
|
3163 | # XXX make this lazy in the future | |
3159 | # don't mutate while iterating, create a copy |
|
3164 | revs = list(revs) | |
3160 | for rev in list(revs): |
|
3165 | # don't mutate while iterating, create a copy | |
3161 |
|
|
3166 | for rev in list(revs): | |
3162 | ui.warn(_('skipping ancestor revision %s\n') % rev) |
|
3167 | if rev in ancestors: | |
3163 | # XXX remove on list is slow |
|
3168 | ui.warn(_('skipping ancestor revision %s\n') % rev) | |
3164 | revs.remove(rev) |
|
3169 | # XXX remove on list is slow | |
3165 | if not revs: |
|
3170 | revs.remove(rev) | |
3166 | return -1 |
|
3171 | if not revs: | |
3167 |
|
3172 | return -1 | ||
3168 | # analyze revs for earlier grafts |
|
3173 | ||
3169 | ids = {} |
|
3174 | # analyze revs for earlier grafts | |
3170 | for ctx in repo.set("%ld", revs): |
|
3175 | ids = {} | |
3171 | ids[ctx.hex()] = ctx.rev() |
|
3176 | for ctx in repo.set("%ld", revs): | |
3172 | n = ctx.extra().get('source') |
|
3177 | ids[ctx.hex()] = ctx.rev() | |
3173 | if n: |
|
3178 | n = ctx.extra().get('source') | |
3174 |
i |
|
3179 | if n: | |
3175 |
|
3180 | ids[n] = ctx.rev() | ||
3176 | # check ancestors for earlier grafts |
|
3181 | ||
3177 | ui.debug('scanning for duplicate grafts\n') |
|
3182 | # check ancestors for earlier grafts | |
3178 |
|
3183 | ui.debug('scanning for duplicate grafts\n') | ||
3179 | for rev in repo.changelog.findmissingrevs(revs, [crev]): |
|
3184 | ||
3180 | ctx = repo[rev] |
|
3185 | for rev in repo.changelog.findmissingrevs(revs, [crev]): | |
3181 | n = ctx.extra().get('source') |
|
3186 | ctx = repo[rev] | |
3182 | if n in ids: |
|
3187 | n = ctx.extra().get('source') | |
3183 | r = repo[n].rev() |
|
3188 | if n in ids: | |
3184 |
|
|
3189 | r = repo[n].rev() | |
3185 | ui.warn(_('skipping revision %s (already grafted to %s)\n') |
|
3190 | if r in revs: | |
3186 | % (r, rev)) |
|
3191 | ui.warn(_('skipping revision %s (already grafted to %s)\n') | |
|
3192 | % (r, rev)) | |||
|
3193 | revs.remove(r) | |||
|
3194 | elif ids[n] in revs: | |||
|
3195 | ui.warn(_('skipping already grafted revision %s ' | |||
|
3196 | '(%s also has origin %d)\n') % (ids[n], rev, r)) | |||
|
3197 | revs.remove(ids[n]) | |||
|
3198 | elif ctx.hex() in ids: | |||
|
3199 | r = ids[ctx.hex()] | |||
|
3200 | ui.warn(_('skipping already grafted revision %s ' | |||
|
3201 | '(was grafted from %d)\n') % (r, rev)) | |||
3187 | revs.remove(r) |
|
3202 | revs.remove(r) | |
3188 |
|
|
3203 | if not revs: | |
3189 | ui.warn(_('skipping already grafted revision %s ' |
|
3204 | return -1 | |
3190 | '(%s also has origin %d)\n') % (ids[n], rev, r)) |
|
|||
3191 | revs.remove(ids[n]) |
|
|||
3192 | elif ctx.hex() in ids: |
|
|||
3193 | r = ids[ctx.hex()] |
|
|||
3194 | ui.warn(_('skipping already grafted revision %s ' |
|
|||
3195 | '(was grafted from %d)\n') % (r, rev)) |
|
|||
3196 | revs.remove(r) |
|
|||
3197 | if not revs: |
|
|||
3198 | return -1 |
|
|||
3199 |
|
3205 | |||
3200 | wlock = repo.wlock() |
|
3206 | wlock = repo.wlock() | |
3201 | try: |
|
3207 | try: |
@@ -257,7 +257,7 b' Show all commands + options' | |||||
257 | debugsuccessorssets: |
|
257 | debugsuccessorssets: | |
258 | debugwalk: include, exclude |
|
258 | debugwalk: include, exclude | |
259 | debugwireargs: three, four, five, ssh, remotecmd, insecure |
|
259 | debugwireargs: three, four, five, ssh, remotecmd, insecure | |
260 | graft: rev, continue, edit, log, currentdate, currentuser, date, user, tool, dry-run |
|
260 | graft: rev, continue, edit, log, force, currentdate, currentuser, date, user, tool, dry-run | |
261 | grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude |
|
261 | grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude | |
262 | heads: rev, topo, active, closed, style, template |
|
262 | heads: rev, topo, active, closed, style, template | |
263 | help: extension, command, keyword |
|
263 | help: extension, command, keyword |
@@ -631,3 +631,33 b' graft works on complex revset' | |||||
631 | grafting revision 13 |
|
631 | grafting revision 13 | |
632 | grafting revision 19 |
|
632 | grafting revision 19 | |
633 | merging b |
|
633 | merging b | |
|
634 | ||||
|
635 | graft with --force (still doesn't graft merges) | |||
|
636 | ||||
|
637 | $ hg graft 19 0 6 | |||
|
638 | skipping ungraftable merge revision 6 | |||
|
639 | skipping ancestor revision 0 | |||
|
640 | skipping already grafted revision 19 (22 also has origin 2) | |||
|
641 | [255] | |||
|
642 | $ hg graft 19 0 6 --force | |||
|
643 | skipping ungraftable merge revision 6 | |||
|
644 | grafting revision 19 | |||
|
645 | merging b | |||
|
646 | grafting revision 0 | |||
|
647 | ||||
|
648 | graft --force after backout | |||
|
649 | ||||
|
650 | $ echo abc > a | |||
|
651 | $ hg ci -m 28 | |||
|
652 | $ hg backout 28 | |||
|
653 | reverting a | |||
|
654 | changeset 29:484c03b8dfa4 backs out changeset 28:6c56f0f7f033 | |||
|
655 | $ hg graft 28 | |||
|
656 | skipping ancestor revision 28 | |||
|
657 | [255] | |||
|
658 | $ hg graft 28 --force | |||
|
659 | grafting revision 28 | |||
|
660 | merging a | |||
|
661 | $ cat a | |||
|
662 | abc | |||
|
663 |
General Comments 0
You need to be logged in to leave comments.
Login now