diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py --- a/mercurial/subrepo.py +++ b/mercurial/subrepo.py @@ -665,6 +665,10 @@ class gitsubrepo(object): out, code = self._gitdir(['cat-file', '-e', revision]) return code == 0 + def _gitisancestor(self, r1, r2): + base = self._gitcommand(['merge-base', r1, r2]).strip() + return base == r1 + def _gitbranchmap(self): 'returns the current branch and a map from git revision to branch[es]' bm = {} @@ -767,17 +771,31 @@ class gitsubrepo(object): self._gitcommand(['merge', '--no-commit', revision]) def push(self, force): + # if a branch in origin contains the revision, nothing to do + current, bm = self._gitbranchmap() + for revision, branches in bm.iteritems(): + for b in branches: + if b.startswith('remotes/origin'): + if self._gitisancestor(self._state[1], revision): + return True + # otherwise, try to push the currently checked out branch cmd = ['push'] if force: cmd.append('--force') - # push the currently checked out branch - current, bm = self._gitbranchmap() if current: + # determine if the current branch is even useful + if not self._gitisancestor(self._state[1], current): + self._ui.warn(_('unrelated git branch checked out ' + 'in subrepo %s\n') % self._relpath) + return False + self._ui.status(_('pushing branch %s of subrepo %s\n') % + (current, self._relpath)) self._gitcommand(cmd + ['origin', current, '-q']) return True else: self._ui.warn(_('no branch checked out in subrepo %s\n' - 'nothing to push') % self._relpath) + 'cannot push revision %s') % + (self._relpath, self._state[1])) return False def remove(self): diff --git a/tests/test-subrepo-git.t b/tests/test-subrepo-git.t --- a/tests/test-subrepo-git.t +++ b/tests/test-subrepo-git.t @@ -134,6 +134,7 @@ user b push changes $ hg push pushing to $TESTTMP/t + pushing branch testing of subrepo s searching for changes adding changesets adding manifests @@ -170,12 +171,44 @@ user a pulls, merges, commits revision f47b465e1bce645dbf37232a00574aa1546ca8d3 $ hg push pushing to $TESTTMP/t + pushing branch testing of subrepo s searching for changes adding changesets adding manifests adding file changes added 2 changesets with 2 changes to 1 files +make upstream git changes + + $ cd .. + $ git clone -q gitroot gitclone + $ cd gitclone + $ echo ff >> f + $ git commit -q -a -m ff + $ echo fff >> f + $ git commit -q -a -m fff + $ git push -q origin testing + +make and push changes to hg without updating the subrepo + + $ cd ../t + $ hg clone . ../td + updating to branch default + cloning subrepo s + checking out detached HEAD in subrepo s + check out a git branch if you intend to make changes + 3 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cd ../td + $ echo aa >> a + $ hg commit -m aa + $ hg push + pushing to $TESTTMP/t + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + update to a revision without the subrepo, keeping the local git repository $ cd ../t