What you need to understand to work on a GitLab project from Cursor. Cursor runs the Git commands for you; your job is to know what each button means, and why.
Three tools, three jobs
Three names come up all the time. They are separate things that work together.
Git
The version-control program. It runs on your computer, records every commit in a hidden .git folder inside the project, manages branches and performs merges. It works without an internet connection.
GitLab
A website that hosts the shared copy of the project. Push and pull exchange commits with it. It adds what Git alone lacks: logins and permissions, merge requests with review, and a backup that isn’t on your laptop.
Cursor
The editor you write code in. Its Source Control panel is a set of buttons that run Git for you: clicking Commit runs git commit. Cursor stores no history of its own.
Git does the versioning, GitLab is where the work is shared, and Cursor is how you drive both. Without Cursor, Git and GitLab would work just the same from the command line.
Your code lives in three places
Git keeps a full copy of the project’s history on your computer. GitLab keeps the shared copy everyone works from. Changes travel between the two only when you say so: nothing reaches GitLab until you push, and nothing from colleagues reaches you until you pull.
Left to right is how your work travels out. The green arrows are the only moments your computer talks to GitLab.
Eight words to know
repository (repo)
A project folder plus its complete history of changes.
commit
A saved snapshot of the project, with a message and an ID like a3f9c21. Commits don’t disappear; you can always go back.
stage (add)
Choose which changed files go into the next commit, so related changes are saved together.
branch
A named line of commits. Work on one branch doesn’t touch another until you merge.
remote / origin
The copy on GitLab. origin is Git’s default name for it.
push / pull
Upload your commits to GitLab / download other people’s commits from it.
merge
Bring the commits of one branch into another.
merge request (MR)
GitLab’s page for proposing, reviewing and performing a merge. GitHub calls it a pull request.
Two branches: main and develop
main holds the stable version: what is released or deployed. It should always work. develop is where day-to-day work happens. When the work on develop is tested and ready, it is merged into main, and main moves forward in one clean step.
Each circle is a commit; time runs left to right. The filled circle is the merge commit that brings develop’s work into main.
Which branch am I on? Cursor shows the current branch in the bottom-left corner of the window. Click it to switch branches or to create a new one. Check it before you start working: it’s the most common source of confusion.
Where the buttons are
Everything happens in the Source Control panel (the branch icon in the left sidebar, or Ctrl+Shift+G; on a Mac ⌃+⇧+G) and in the status bar at the bottom of the window.
SOURCE CONTROL✓ ⟳ ···
1
Add login form validation
2
✓ Commit
Staged Changes1
Msrc/login.ts−
Changes2
Msrc/styles.css+3
Usrc/validate.ts+
4⎇ develop⟳ 2↓ 1↑5
1Commit message. A short sentence saying what the change does.
2Commit saves the staged changes in your local repository. Afterwards the button often becomes Sync Changes, which pulls and then pushes.
3+ stages a file, − unstages it. M means modified, U a new, untracked file.
4Branch name. Click to switch branches or create one.
5Sync.2↓: two commits on GitLab you don’t have yet. 1↑: one of yours not yet pushed. Click to sync.
A simplified sketch; the layout varies a little between Cursor versions. The ··· menu at the top of the panel holds every Git action: Pull, Push, Clone, Branch, Merge…
Once: clone the project
Copy the clone URL on GitLab.On the project page, click the blue Code button and copy the HTTPS (or SSH) address.
Clone in Cursor.Command Palette (Ctrl/⌘+Shift+P) → Git: Clone → paste the URL → choose a folder → open it.
Sign in when asked.With HTTPS, GitLab wants your username and a personal access token instead of your password (create one under your avatar → Preferences → Access tokens). With SSH, add your public key to GitLab once.
Switch to develop.Click the branch name in the bottom-left and pick origin/develop. Cursor creates your local develop branch and links it to GitLab’s.
Every day: the loop
Check you’re on develop.Bottom-left corner of the window.
Pull before you start.Click the sync indicator, or ··· → Pull. You start from the latest version and avoid conflicts later.
Edit files as usual.Changed files appear under Changes in the Source Control panel; click one to see a side-by-side diff.
Stage the files that belong together.Click + next to each file, or next to Changes to stage all. If you stage nothing, Cursor offers to commit everything.
Commit with a clear message.Small and often: one logical change per commit. Commits are local, so this is safe and private.
Push to share it.Click Sync Changes or the ↑ in the status bar. Now it is on GitLab, and backed up.
Commit is not push. A commit exists only on your computer. If your laptop dies before you push, the commit is gone. Push at least at the end of every working session.
Merging develop into main
There are two ways. The merge request on GitLab is the better one: you see every change before it lands, and GitLab keeps a record.
On GitLab (recommended)
Push develop. On GitLab: Merge requests → New merge request, source develop, target main. Review the Changes tab, then click Merge. Untick “Delete source branch” so develop stays.
In Cursor
Commit and push everything on develop. Switch to main and pull. Then ··· → Branch → Merge Branch… → develop. Push main, and switch back to develop.
The other direction. If someone fixes something directly on main, bring it into develop the same way (merge main into develop) so the two branches don’t drift apart.
Merge conflicts
A conflict happens when two branches changed the same lines differently. Git can’t guess which version is right, so it stops and asks you. This is normal, and nothing is lost.
Changes to different lines or files merge automatically. Only the same line, changed differently on both sides, needs a decision.
Cursor lists the affected files under Merge Changes and marks the spot in each file:
Accept Current Change | Accept Incoming Change | Accept Both Changes | Compare Changes
<<<<<<< HEAD (Current Change)
const timeout = 45;
=======
const timeout = 60;
>>>>>>> develop (Incoming Change)
Pick a version with the links above the conflict, or edit the text by hand until it’s right.Current is the branch you are on; Incoming is the branch being merged in. No marker lines (<<<, ===, >>>) may remain.
Save and stage the file with +.
Commit to complete the merge, then push.Changed your mind? ··· → Abort Merge puts everything back as it was before the merge.
Cheat sheet
I want to…
In Cursor
What Git does
get the project the first time
Command Palette → Git: Clone
clone: copies the repo and its history
get colleagues’ changes
Sync ↓, or ··· → Pull
pull: fetch + merge into your branch
choose what to save
+ next to files
add: stages changes
save a snapshot
Message, then Commit
commit: records it locally
share my work
Sync Changes, or ↑
push: uploads commits to GitLab
change branch
Branch name, bottom-left
switch
release develop to main
Merge request on GitLab
merge
throw away an edit
↶ (Discard Changes) by the file
restore: back to the last commit. Can’t be undone.
look at history
Timeline, or the Source Control graph
log
Five habits that prevent most trouble
Pull first.Start every session by pulling. Most conflicts come from working on an old version.
Work on develop.Main changes only through a merge. Committed on main by mistake? Stop and ask before pushing.
Commit before switching branches.With uncommitted changes, a switch either fails or carries them along to the other branch.
Small commits, clear messages.“Fix date format on invoice” beats “changes”. Small commits are easier to review and to undo.
Push every day.Unpushed work exists only on your machine. GitLab is your backup.