jenkinsci / jenkinsci/git-plugin

[JENKINS-39693] Surprising behavior of "catching up" with multiple branches.

Open
#2,987 3 comments 0 reactions 0 assignees View on GitHub
component:git-plugin enhancement imported-jira-issue priority:minor resolution:unresolved
Dominant language
Java
Stars
694
Forks
1.1k
Avg merge
1h 29m
Merged PRs (30d)
3

Description

I was confused by the git plugin's behavior when catching up. I expected it to run a build for the head of each branch that hadn't been built.

Instead it seems to run a build for each unbuilt leaf, ignoring any branch heads that have children. I first noticed it when master wasn't being built and wasted a bunch of time worrying that I had something wrong with my branch specifier, e.g. that ** only matched paths that contains / or some such.

This means that e.g. I can have branches that do not have current status-es displayed in the GitHub repository.

You can recreate it by creating a new repository on e.g. github and using the following script to make/push a bunch of commits (leave the last few lines commented out):

commits.sh

git clone http:////foo

cd foo
echo 'FOO' >> 'master'
git add master
git commit -a -m 'master'
git push origin
git checkout -b feature/foo
echo 'FEATURE' >> feature
git add feature
git commit -a -m 'feature'
git push --set-upstream origin feature/foo
git checkout -b feature/foo2
echo 'FEATURE' >> feature2
git add feature2
git commit -a -m 'feature2'
git push --set-upstream origin feature/foo2
git checkout feature/foo
echo "YAY" >> yay
git add yay
git commit -a -m 'yay'
git push
git checkout master
git checkout -b bugfix/bar
echo 'BUG' >> bug
git add bug
git commit -a -m 'bug'
git push --set-upstream origin bugfix/bar
git checkout master
# echo 'DOG' >> pet
# git add pet
# git commit -a -m 'pet'
# git push

And then setting up a simple job that refers to the repository and tracks all branches (e.g. **) and tha tis trigger-able by the /build?token=ape URL, e.g. with this Jenkins Job Builder configuration:

foo.yaml

- job:

name: foo
description: |
HANDS OFF! This jobs is managed by Jenkins Job Builder. Any changes
HANDS OFF! you make will be overwritten the next time it runs.

FOO!
auth-token: 'ape'
scm:
- git:
url: http:////foo.git
git-config-name: 'Your Name'
git-config-email: 'you@​foo.com'
builders:
- shell: |
#!/bin/sh -eu
printenv | sort
ls


Finally, trigger the job by URL, e.g. using {{httpie} like so:

http 192.168.99.100:8080/job/foo/build?token=ape

If you run the script with the final few lines commented out, you'll end up with a repository that looks something like so:

* [91cefe8] (origin/bugfix/bar, bugfix/bar) bug

| * [f294c69] (origin/feature/foo, feature/foo) yay
| | * [422983f] (origin/feature/foo2, feature/foo2) feature2
| |/
| * [4e86cfc] feature
|/
* [2e52f18] (HEAD -> master, origin/master, origin/HEAD) master
* [84d9d20] Initial commit

and you'll build feature/foo, feature/foo2, and bugfix/bar, but not master.

If you clean everything up, uncomment out the final few lines of the bash script (which throws another commit onto master so that its head is also a leaf node), you'll end up with a repo like so:

* [7771686] (HEAD -> master, origin/master, origin/HEAD) pet

| * [73d7c6d] (origin/bugfix/bar, bugfix/bar) bug
|/
| * [43b1670] (origin/feature/foo, feature/foo) yay
| | * [a468e73] (origin/feature/foo2, feature/foo2) feature2
| |/
| * [baa1264] feature
|/
* [46a64cb] master
* [41f8553] Initial commit

And you'll build run 4 builds (features, bugfix, and master).

It would be useful if this behavior were documented somewhere.

I think it would be even more useful if it ran the builds that were necessary to bring all of the branches up to date.

Thanks!

---
Originally reported by hartzell, imported from: Surprising behavior of "catching up" with multiple branches.


  • status: Open
  • priority: Minor
  • component(s): git-plugin
  • label(s): git
  • resolution: Unresolved
  • votes: 2
  • watchers: 4
  • imported: 2025-12-02

Raw content of original issue

I was confused by the git plugin's behavior when catching up. I expected it to run a build for the head of each branch that hadn't been built.

Instead it seems to run a build for each unbuilt leaf, ignoring any branch heads that have children. I first noticed it when master wasn't being built and wasted a bunch of time worrying that I had something wrong with my branch specifier, e.g. that ** only matched paths that contains / or some such.

This means that e.g. I can have branches that do not have current status-es displayed in the GitHub repository.

You can recreate it by creating a new repository on e.g. github and using the following script to make/push a bunch of commits (leave the last few lines commented out):

commits.sh

git clone http://<server>/<user>/foo

cd foo
echo 'FOO' >> 'master'
git add master
git commit -a -m 'master'
git push origin
git checkout -b feature/foo
echo 'FEATURE' >> feature
git add feature
git commit -a -m 'feature'
git push --set-upstream origin feature/foo
git checkout -b feature/foo2
echo 'FEATURE' >> feature2
git add feature2
git commit -a -m 'feature2'
git push --set-upstream origin feature/foo2
git checkout feature/foo
echo "YAY" >> yay
git add yay
git commit -a -m 'yay'
git push
git checkout master
git checkout -b bugfix/bar
echo 'BUG' >> bug
git add bug
git commit -a -m 'bug'
git push --set-upstream origin bugfix/bar
git checkout master
# echo 'DOG' >> pet
# git add pet
# git commit -a -m 'pet'
# git push

And then setting up a simple job that refers to the repository and tracks all branches (e.g. **) and tha tis trigger-able by the /build?token=ape URL, e.g. with this Jenkins Job Builder configuration:

foo.yaml

- job:

name: foo
description: |
HANDS OFF! This jobs is managed by Jenkins Job Builder. Any changes
HANDS OFF! you make will be overwritten the next time it runs.

FOO!
auth-token: 'ape'
scm:
- git:
url: http://<server>/<user>/foo.git
git-config-name: 'Your Name'
git-config-email: 'you@foo.com'
builders:
- shell: |
#!/bin/sh -eu
printenv | sort
ls


Finally, trigger the job by URL, e.g. using {{httpie} like so:


http 192.168.99.100:8080/job/foo/build?token=ape


If you run the script with the final few lines commented out, you'll end up with a repository that looks something like so:


* [91cefe8] (origin/bugfix/bar, bugfix/bar) bug

| * [f294c69] (origin/feature/foo, feature/foo) yay
| | * [422983f] (origin/feature/foo2, feature/foo2) feature2
| |/
| * [4e86cfc] feature
|/
* [2e52f18] (HEAD -> master, origin/master, origin/HEAD) master
* [84d9d20] Initial commit

and you'll build feature/foo, feature/foo2, and bugfix/bar, but not master.

If you clean everything up, uncomment out the final few lines of the bash script (which throws another commit onto master so that its head is also a leaf node), you'll end up with a repo like so:


* [7771686] (HEAD -> master, origin/master, origin/HEAD) pet

| * [73d7c6d] (origin/bugfix/bar, bugfix/bar) bug
|/
| * [43b1670] (origin/feature/foo, feature/foo) yay
| | * [a468e73] (origin/feature/foo2, feature/foo2) feature2
| |/
| * [baa1264] feature
|/
* [46a64cb] master
* [41f8553] Initial commit

And you'll build run 4 builds (features, bugfix, and master).

It would be useful if this behavior were documented somewhere.

I think it would be even more useful if it ran the builds that were necessary to bring all of the branches up to date.

Thanks!

  • environment: Official Jenkins Docker image (and this week's Jenkinsci weekly image

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.