Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-8756

Support multiple fetch refspecs

XMLWordPrintable

    • Icon: New Feature New Feature
    • Resolution: Fixed
    • Icon: Major Major
    • git-plugin
    • None

      In trying to integrate with the Gerrit Trigger plugin, I want to be able to confirm that the $GERRIT_REFSPEC patch can be merged with the tip of an integration branch. However, using $GERRIT_REFSPEC as the "Refspec" in the repo configuration (as explained in the Gerrit Trigger plugin) causes the git plugin to only fetch $GERRIT_REFSPEC from the remote.

      That causes a problem with the "Merge" options, because configuring the plugin to merge to the "origin" remote's "master" branch makes it never fetch refs/heads/master from the remote. $GERRIT_REFSPEC is generally set to something like "refs/changes/69/669/1", so it fetches that change into the workspace. But when it tries to do the merge, it only runs "git rev-parse origin/master", but the "refs/remotes/origin/master" refspec was never fetched, so it ends up merging the $GERRIT_REFSPEC onto a stale master revision.

      I can think of a few ways to update the plugin to make this easy:

      1. in the "Repositories" configuration, allow multiple "Refspec" fields to be entered, and fetch each one separately (note, this will cause an issue with any commands that use FETCH_HEAD, as each new fetch results in an updated FETCH_HEAD)
      2. in the "Branch to merge to" configuration, take an optional "Refspec" field that allows a separate refspec to be fetched just before attempting the merge
      3. without updating the configuration, before doing the merge, check if the configured repo Refspec is non-standard (more accurately, if it doesn't match "refs/heads/${target_branch}:refs/remotes/${target_remote}/${target_branch}"), then also run "fetch ${target_remote} refs/heads/${target_branch}" before attempting the merge

      My current configuration:

      URL: ssh://gerrit:29418/Project/Name
      Repo Name: gerrit
      Refspec: $GERRIT_REFSPEC
      
      Checkout/merge to local branch: master
      Merge before build: Yes
        - Name of repo: gerrit
        - Branch to merge to: master
      

      The git plugin performs these commands:

      Fetching changes from the remote Git repository
      Fetching upstream changes from ssh://gerrit:29418/Project
      [gerrit-verify-build] $ /usr/bin/git fetch -t ssh://gerrit:29418/Project refs/changes/01/101/1
      [gerrit-verify-build] $ /usr/bin/git ls-tree HEAD
      [gerrit-verify-build] $ /usr/bin/git rev-parse FETCH_HEAD
      Commencing build of Revision 7e2748e4312146f1f3b090ec3d9c70a7acfc16af (master)
      GitAPI created
      Merging Revision 7e2748e4312146f1f3b090ec3d9c70a7acfc16af (master) onto master
      [gerrit-verify-build] $ /usr/bin/git rev-parse gerrit/master
      [gerrit-verify-build] $ /usr/bin/git checkout -f f5f1543886606eee0ab258316c276e21ba5f13a2
      [gerrit-verify-build] $ /usr/bin/git branch -a
      [gerrit-verify-build] $ /usr/bin/git rev-parse master
      [gerrit-verify-build] $ /usr/bin/git rev-parse remotes/gerrit/master
      [gerrit-verify-build] $ /usr/bin/git branch -D master
      [gerrit-verify-build] $ /usr/bin/git checkout -b master f5f1543886606eee0ab258316c276e21ba5f13a2
      [gerrit-verify-build] $ /usr/bin/git merge 7e2748e4312146f1f3b090ec3d9c70a7acfc16af
      Warning : There are multiple branch changesets here
      [gerrit-verify-build] $ /usr/bin/git rev-parse FETCH_HEAD
      [gerrit-verify-build] $ /usr/bin/git log -1 --pretty=format:%P 7e2748e4312146f1f3b090ec3d9c70a7acfc16af
      [gerrit-verify-build] $ /usr/bin/git whatchanged --no-abbrev -M --pretty=raw e79d78e39c67b324f95f604ba8e5fbe49232882d..7e2748e4312146f1f3b090ec3d9c70a7acfc16af
      

      The problem is that it only fetches the $GERRIT_REFSPEC (so it grabs the gerrit patch correctly), but it never fetches "remotes/gerrit/master". Therefore, the merge to master (in this case, f5f15438) is merging to an old revision of master, not the latest revision.

      What I would expect it to do is:

      $ git fetch -t $GERRIT_REFSPEC
      $ git rev-parse FETCH_HEAD               # (call it 2222222)
      $ git fetch gerrit master
      $ git rev-parse [remotes/]gerrit/master  # (call it 1111111)
      $ git branch -D master
      $ git checkout -b master 1111111
      $ git merge 2222222
      $ .. continue
      

            abayer Andrew Bayer
            madcoder Joe Hansche
            Votes:
            9 Vote for this issue
            Watchers:
            10 Start watching this issue

              Created:
              Updated:
              Resolved: