Ravindra BagaleCourses & study guides मराठी

Chapter 20: Jenkins Manual Jobs — Install, Configure and Freestyle

20.8 Git integration in a Freestyle project

Why: the problem

A build is only useful if it builds the right code. When a Freestyle job checks out from Git, four small fields decide everything: the repository URL, the credential ID, the branch specifier, and what to do with old files in the workspace. Get the branch wrong and a release job quietly builds develop instead of main; at a Hyderabad SaaS company that is how an untested feature reached customers. Forget to clean the workspace and a deleted file still sits there from an old build, so tests pass in Jenkins but fail on a fresh machine. The Git plugin also sets useful variables like GIT_COMMIT and GIT_BRANCH, which you should print and save so you can always answer "which commit is live?". In this lesson you will push the badge-api project to Gitea, connect a Freestyle job to it with the credential from 20.7, build a chosen branch, wipe the workspace safely, and record the exact commit of every build.

What we will build

You will push a small Node.js project to the private Gitea repo, then create the Freestyle job badge-api-ci with Source Code Management set to Git, the gitea-badge-token credential and branch */main. You will add Additional Behaviours: Clean before checkout and Check out to specific local branch. You will print GIT_COMMIT, GIT_BRANCH and the commit message, save them into build-info.txt, and test a second branch with a branch parameter.

What: every term in plain English

  • SCM — Source Code Management. In Freestyle, the Git section of the job.
  • Repository URL — Where to clone from, here http://gitea:3000/ravi/badge-api.git.
  • Branch specifier — Which branch to build, like */main.
  • GIT_COMMIT — The full commit hash this build checked out.
  • Detached HEAD — Jenkins checks out a commit, not a branch, by default.
  • Clean before checkout — Runs git clean -fdx so old untracked files are removed.
Create the project on your laptop Add the remote Push Point the job at Gitea Add behaviours
Wire Git into a Freestyle job

How: step by step

  1. Create the project on your laptop

    mkdir badge-api && cd badge-api && git init -b main
    

    What it does: A new local repo.

    Output

    Initialized empty Git repository in /home/ravi/badge-api/.git/
    
  2. Add the remote

    git remote add origin http://localhost:3000/ravi/badge-api.git
    

    What it does: From the laptop, Gitea is on localhost:3000.

    Output

    (no output)
    
  3. Push

    git add . && git commit -m "badge api first version" && git push -u origin main
    

    What it does: Gitea asks for user and token.

    Output

    * [new branch]      main -> main
    
  4. Point the job at Gitea

    New Item > badge-api-ci > Freestyle > Source Code Management: Git > URL http://gitea:3000/ravi/badge-api.git > Credentials gitea-badge-token > Branch */main
    

    What it does: From Jenkins, Gitea is the hostname gitea.

    Output

    No error under the URL field
    
  5. Add behaviours

    Additional Behaviours > Clean before checkout; Check out to specific local branch (main)
    

    What it does: Fresh workspace and a real branch name.

    Output

    Saved
    

Example 1: Print and save exactly what was built

Stack. Git plugin, Gitea

Goal. Print and save exactly what was built.

Execute shell

set -e
echo "branch: $GIT_BRANCH"
echo "commit: $GIT_COMMIT"
echo "prev:   ${GIT_PREVIOUS_SUCCESSFUL_COMMIT:-none}"
git log -1 --format="author: %an%nmsg:    %s"
git status --short | wc -l
printf "job=%s\nbuild=%s\ncommit=%s\nbranch=%s\n" "$JOB_NAME" "$BUILD_NUMBER" "$GIT_COMMIT" "$GIT_BRANCH" > build-info.txt
cat build-info.txt

What each line does

  • $GIT_BRANCH — Set by the Git plugin, like origin/main.
  • $GIT_COMMIT — The exact commit hash.
  • GIT_PREVIOUS_SUCCESSFUL_COMMIT — The commit of the last green build. Useful for change lists.
  • git status --short | wc -l — 0 means the checkout is clean.
  • build-info.txt — A small file you can archive and ship with the app.

Green output

Cloning the remote Git repository
Cloning repository http://gitea:3000/ravi/badge-api.git
 > git fetch --tags --force --progress -- http://gitea:3000/ravi/badge-api.git +refs/heads/*:refs/remotes/origin/*
Checking out Revision 9c41d2e7a1b0f3c5d6e7f8091a2b3c4d5e6f7a8b (refs/remotes/origin/main)
 > git checkout -b main 9c41d2e7a1b0f3c5d6e7f8091a2b3c4d5e6f7a8b
Commit message: "badge api first version"
branch: origin/main
commit: 9c41d2e7a1b0f3c5d6e7f8091a2b3c4d5e6f7a8b
prev:   none
author: ravi
msg:    badge api first version
0
job=badge-api-ci
build=1
commit=9c41d2e7a1b0f3c5d6e7f8091a2b3c4d5e6f7a8b
branch=origin/main

Expected result. You can answer "which commit is this build?" for every run.

Example 2: Build any branch with a parameter

Stack. Git, parameters

Goal. Build any branch with a parameter.

Job settings

This project is parameterized:
  String Parameter: BRANCH  default: main
Source Code Management > Git > Branch Specifier: */${BRANCH}

make-branch.sh (laptop)

cd badge-api
git switch -c feature/gold-badge
echo "// gold badge rule" >> src/badges.js
git commit -am "add gold badge rule"
git push -u origin feature/gold-badge
curl -s -X POST -u "ravi:$JENKINS_TOKEN" \
  "http://localhost:8080/job/badge-api-ci/buildWithParameters?BRANCH=feature/gold-badge" \
  -o /dev/null -w "queued %{http_code}\n"

What each line does

  • */${BRANCH} — The branch field can use a parameter.
  • buildWithParameters?BRANCH=... — Starts the job for that branch.
  • git switch -c — Creates and moves to a new branch.

Green output

* [new branch]      feature/gold-badge -> feature/gold-badge
queued 201
# Console of build #2:
Checking out Revision 4be1... (refs/remotes/origin/feature/gold-badge)
branch: origin/feature/gold-badge

Expected result. One job can test any branch on demand.

Example 3: Prove Clean before checkout removes leftovers

Stack. Git plugin behaviours

Goal. Prove Clean before checkout removes leftovers.

Execute shell (test once)

ls leftover.txt 2>/dev/null && echo "leftover still here" || echo "workspace is clean"
echo "temp" > leftover.txt

What each line does

  • First build — Creates leftover.txt, an untracked file.
  • Second build — Clean before checkout runs git clean -fdx first, so the file is gone.
  • Without the behaviour — The file would survive and could hide bugs.

Green output

# build 3
workspace is clean
# build 4
 > git clean -fdx
workspace is clean

Expected result. Every build starts from the commit only, like a fresh laptop.

Verify: did it work?

  1. Job knows its SCM

    curl -s -u ravi:$JENKINS_TOKEN http://localhost:8080/job/badge-api-ci/config.xml | grep -o "http://gitea:3000/ravi/badge-api.git"
    

    What it does: URL is saved.

    Output

    http://gitea:3000/ravi/badge-api.git
    
  2. Commit recorded

    curl -s -u ravi:$JENKINS_TOKEN "http://localhost:8080/job/badge-api-ci/lastBuild/git/api/json?tree=lastBuiltRevision[SHA1]"
    

    What it does: The Git plugin keeps the hash.

    Output

    {"lastBuiltRevision":{"SHA1":"4be1..."}}
    

When it is red 1

Failed to connect to repository : Command "git ls-remote -h -- http://gitea:3000/ravi/badge-api.git HEAD" returned status code 128

Cause. Bad URL, wrong credential, or network.

Fix, step by step

  1. Test from the container: docker exec jenkins git ls-remote http://gitea:3000/ravi/badge-api.git.
  2. Pick the right credential ID.
  3. Check the repo name.

When it is red 2

Couldn't find any revision to build. Verify the repository and branch configuration for this job.

Cause. The branch does not exist on the remote.

Fix, step by step

  1. Check spelling: main vs master.
  2. git ls-remote --heads to list branches.

When it is red 3

fatal: detected dubious ownership in repository

Cause. The workspace was created by another user, often after running as root.

Fix, step by step

  1. Fix owner: chown -R jenkins:jenkins the workspace.
  2. Never run builds as root.

When it is red 4

stderr: remote: Repository not found

Cause. The token user has no access to a private repo, or the owner or name is wrong.

Fix, step by step

  1. Open the repo in Gitea as that user.
  2. Add the user as a collaborator with Read.
  3. Fix the owner part of the URL.

Cleanup

  1. Delete the feature branch

    git push origin --delete feature/gold-badge
    

    What it does: Removes it from Gitea.

    Output

    - [deleted]         feature/gold-badge
    

Ravindra Bagale's Tip

Kuthla commit build zala te nehmi print kara: GIT_COMMIT. Lakshat theva!

Practice tasks

Easy List branches

Why: Know the remote.

What to do: git ls-remote --heads from Jenkins.

How:
  1. docker exec jenkins git ls-remote --heads URL.

Check: Branches printed.

Medium Shallow clone

Why: Speed.

What to do: Turn on shallow clone depth 1.

How:
  1. Advanced clone behaviours.

Check: Clone is faster.

Hard Tag builds

Why: Traceability.

What to do: Push a git tag build-N after green builds.

How:
  1. Use a credential with write.

Check: Tags appear in Gitea.

Easy Say Git in Freestyle jobs in two lines

Why: If you can say it simply, you understand it. Juniors and interviewers want the short version first.

What to do: Write two short lines about Git in Freestyle jobs for a fresher who knows only Linux basics.

How:
  1. Write what problem it solves.
  2. Write the one command or menu you use for it.
  3. Read it aloud to a friend.

Check: A fresher understands it without asking a question.

Easy Start a fresh lab Jenkins

Why: Practice needs a throwaway Jenkins. If you break it, you delete it and start again.

What to do: Run Jenkins LTS in Docker with a named volume.

How:
  1. docker volume create jenkins_home
  2. docker run -d --name jenkins -p 8080:8080 -v jenkins_home:/var/jenkins_home jenkins/jenkins:lts-jdk17
  3. docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword

Check: The Jenkins unlock page opens on localhost:8080.

Medium Break it on purpose

Why: You must know the red message by face. During an outage there is no time to read slowly.

What to do: Cause one error from the "When it is red" part of this lesson and fix it.

How:
  1. Follow the error section.
  2. Copy the exact message into your notes.
  3. Write the fix in one line.

Check: You fixed it using only the steps, without searching the web.

Medium Write a one-page runbook

Why: At 2 a.m. nobody remembers where a file lives. A short page saves the on-call person.

What to do: Write a runbook page for this lesson.

How:
  1. Title, when to use, exact command, how to check, how to undo.

Check: A teammate can follow it alone.

Medium Repeat it on a cloud VM

Why: A laptop is not a server. Real Jenkins runs on EC2 or a company VM.

What to do: Do the main steps of this lesson again on a small Ubuntu 22.04 EC2 instance.

How:
  1. Launch t3.small with 20 GB disk.
  2. Open port 22 only to your IP.
  3. Repeat the steps and compare the output.

Check: Same green output on the VM as on your laptop.

Hard Explain it like an interview

Why: Interviewers want real stories, not definitions.

What to do: Record a 60 second answer about this lesson.

How:
  1. Say the problem, the command you ran, and one error you hit.

Check: Your answer has a real command and a real error message.

Hard Draw the flow top to bottom

Why: A drawing shows who talks to whom and in what order.

What to do: Draw this lesson as boxes from top to bottom.

How:
  1. Start at the developer push, go through the controller and agent, end at the result.

Check: Each box matches a real thing you saw on screen.

Homework: try at home

Try at home

Add a second repo, badge-ui, and a job that checks it out on branch develop. Print GIT_COMMIT and save build-info.txt there too.

Recap

  • URL, credential ID and branch decide what is built.
  • Clean before checkout keeps builds honest.
  • GIT_COMMIT tells you exactly what was built.
  • Parameters let one job build any branch.
  • Test Git from inside the container when it fails.

FAQ

HTTPS or SSH for Jenkins?

Both work. HTTPS with a token is simpler in labs; SSH keys are common in companies.

Why gitea:3000 in Jenkins but localhost:3000 on my laptop?

Containers on the ci network reach each other by name.

Should Jenkins push to Git?

Only with a separate write credential, and only when needed.

What does */main mean?

Any remote (the star) and the branch main. It matches origin/main. You can also write refs/heads/main to be exact.

Can one job watch many branches?

Freestyle can use a pattern like /feature/, but builds and history get mixed. Multibranch Pipeline (next chapter) gives each branch its own job, which is cleaner.

Interview questions

  1. How do you know which commit a Jenkins build used?

    The Git plugin sets GIT_COMMIT and stores lastBuiltRevision; print and archive it.

  2. Couldn't find any revision to build — cause?

    Branch specifier does not match any remote branch.

Quick quiz

Q1. Which variable holds the commit?

GIT_COMMIT.

Q2. Why clean before checkout?

To remove untracked files from old builds.

Q3. Why is Jenkins in detached HEAD by default?

It checks out a commit, not a local branch.

Samajla ka?

Ravi Sir's Cards for this lesson

मराठी cards