jenkinsci / jenkinsci/git-plugin
[JENKINS-39693] Surprising behavior of "catching up" with multiple branches.
- 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):
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:
- 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.
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.shgit 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 pushAnd 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
lsFinally, trigger the job by URL, e.g. using {{httpie} like so:
http 192.168.99.100:8080/job/foo/build?token=apeIf 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 commitand 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 commitAnd 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
Assessment
This issue has not been assessed yet.