nx1.info | Git

useful tips & Guides https://longair.net/blog/2009/04/16/git-fetch-and-merge/
Table of Contents: ------------------ Branches: list branches create branch switch to branch push new branch to remote remove old unused branches rename old unused branches Account / Credentials: change git credentials make mac remember ssh passphrase Merging & Remote Syncing: incorporate changes from master combine local & remote branch selective merging temporarily sync branch cherry pick merge request sync local commits when remote moved ahead (conflict-safe) Repository Setup: make existing folder into git repo & add remote

List branches: [^]

git branch --list        # local only
git branch --list -all   # remotes too

Create new local branch [^]

> git checkout -b newbranch
# or with git switch:
> git switch -c newbranch

Switch to existing branch [^]

> git checkout branch_name
# or with git switch:
> git switch branch_name

Push new branch to remote [^]

> git push -u origin newbranch

How to change git credentials: [^]

To check git credentials (in repo)
> git config user.name
> git config user.email
> git config --list
option 1:
export GIT_AUTHOR_NAME="nk"
export GIT_AUTHOR_EMAIL="n@k.com"
export GIT_COMMITTER_NAME="nk"
export GIT_COMMITTER_EMAIL="n@k.com"
Option 2: to update (global):
git config --global user.name "nk"
git config --global user.email "n@k.com"
local:
git config user.name "nk"
git config user.email "n@k.com"

How to incorporate changes from master branch into current branch [^]

Option 1:
> git checkout mybranch
> git merge master_branch
Option 2:
> git checkout mybranch
> git rebase master_branch
Option 3:
git checkout mybranch
git stash push -m 'wip tree branch before pulling'
git pull --rebase origin master_branch
# fix any merge conflicts
git stash pop

How to combine changes on a local branch with a remote branch and push them [^]

Assuming you already have commited the changes locally. stash uncommited changes.
> git stash
fetch and merge changes from remote branch
> git fetch origin staging
> git merge origin/staging
push to local branch as specified remote branch.
> git push origin sb_tree:staging
unpop changes if needed:
> git stash pop

How to make mac remember ssh passphrase. [^]

> ssh-add --apple-use-keychain ~/.ssh/id_rsa
and in ~/.ssh/config add the following:
Host *
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/id_rsa
rebash to view listed keys do:
> ssh-add -l

Selective merging. [^]

What happened: new branch master was created from tree. too many changes were added to tree, master is still the same. we want to selecively merge specific lines from the updated tree branch into master. 1. update origin listing
> git fetch
> git status:
On branch tree
Your branch is behind 'origin/tree' by 6 commits, and can be fast-forwarded.
  (use "git pull" to update your local branch)

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   smartbench/debug/send_messages.py

no changes added to commit (use "git add" and/or "git commit -a")
2. Switch to the master branch
> git checkout master
x1@pc:~/projects/matoha-smartbench$ git log --oneline
00fa98c (HEAD -> master, origin/master, tree) supress kafka messages to CRITIAL only
We are in the right place on this branch but we want to selectively merge some changes from the new tree to see the which files are different between the master branch and the updated tree branch use:
> git diff master origin/tree --name-only
x1@Normans-Mac-mini:~/projects/matoha-smartbench$ git diff master origin/tree --name-only
.gitlab-ci.yml
logger.py
run_smartbench.sh
smartbench/app_gui/Dockerfile
smartbench/app_gui/blocks/results_block.py
smartbench/app_gui/camera_capture/basler_capture.py
smartbench/app_gui/camera_capture/camera_capture.py
smartbench/app_gui/camera_capture/camera_manager.py
smartbench/app_gui/camera_capture/camera_worker_thread.py
smartbench/app_gui/camera_capture/test_camera_manager.py
smartbench/app_gui/deepstream_processor.py
smartbench/app_gui/kafka_handler.py
smartbench/app_gui/main_gui.py
smartbench/app_gui/run.sh
smartbench/app_gui/test_main_gui.py
smartbench/barcode/barcode_scanner.py
smartbench/data_manager/api_submitter.py
smartbench/data_manager/data_manager.py
smartbench/data_manager/decision_tree/decision_tree.py
smartbench/data_manager/public_api.py
smartbench/get_details.py
smartbench/matoha_kafka/matoha_kafka.py
smartbench/metal_detection/metal_detection.py
smartbench/metal_detection/run_metal_detection.py
smartbench/rfid/rfid.py
smartbench/weighing_scale/weighing_scale.py
as you can see there are a crapton. to selectively merge specific bits we can do the following using pycharm. In settings, do: Git --> Branches... then select remote/origin/tree --> compare with `master' This will show all the commits that exist in origin/tree but do not exist in master and vice versa. clicking on a commit will show the files that were changed on the commit. right clicking on a file and doing show diff will then show the diffs for the specific file. use compare with local accept / reject the changes we want. check files using
> git diff
git add files and commit.

Making an existing folder into a git repo and adding a remote. [^]

First create a repo on gitlab / github. locally:
git init --initial-branch=main --object-format=sha1
git remote add origin git@gitlab.com:NormanKhan/kafka_tests.git
git add .
git commit -m "Initial commit"
git push --set-upstream origin main

Removing old unused Branches. [^]

First check the branch you are going to delete for diffrences between it and the branch you want to keep (i.e. master)
> git log master..origin/display_collection_name --oneline
If this line returns anything, it means that there are commits that exist on the old branch that do not exist on the master branch. (If you want to know the other way, just flip the order of the branches i.e.
git log origin/display_collection_name..master --oneline   # This will return much much more haha.
In this case it returned the following:
3215915 (origin/display_collection_name) gui stuff
To see what those changes were explicitly, one can do:
git show 3215915
Once happy with the state of the code, the branch may be deleted using:
# Delete a local branch
git branch -d branch_name      # safe - refuses if unmerged
git branch -D branch_name      # FORCE DELETE REGARDLESS!!!

# Delete from remote (GitLab)
git push origin --delete branch_name

Renaming old unused branches [^]

Sometimes there can be old branches that we do not want to delete, case in point we have an old branch called "main" from before we showed up, this guy is still cluttering both gitlab and git, We don't want to delete it exactly but we don't want it there because it is slightly confusing. We can rename the brach locally by doing:
git branch -m main archive/main-old
Then we can push the renamed branch by doing:
git push origin archive/main-old
Finally, we can delete the old branch meaning it no longer clogs shit up:
git push origin --delete main

Temporarily sync a branch with another [^]

Problem: You've created a branch and have got everything right on it but in order to test / build on CI it needs to be on a specific named branch. e.g: I want merge_staging to match master_staging for a bit then i want to revert merge_staging back to how it was. 1. Get the commit hash for merge_staging
> git rev-parse merge_staging
43996b0e8a894dc2abec361d9bc4fb01058f4923
or:
> git log -1 merge_staging
and the commit hash will be there in the first line:
x1@Normans-Mac-mini:~/projects/matoha-smartbench$ git log -1 merge_staging
commit 43996b0e8a894dc2abec361d9bc4fb01058f4923 (origin/merge_staging, merge_staging)
2. Create an immutable local safety tag.
> git tag merge_staging_backup merge_staging
Make sure the tag was created:
> git rev-parse merge_staging_backup
43996b0e8a894dc2abec361d9bc4fb01058f4923
3. Switch to merge_staging branch
> git checkout merge_staging
4. make merge_staging match master_staging
> git reset --hard master_staging
This moves the branch pointer for merge_staging to match master_staging verify the match with
x1@Normans-Mac-mini:~/projects/matoha-smartbench$ git log -1 --oneline
9ad49eb (HEAD -> merge_staging, origin/master_staging, master_staging) chore: remove extraneous debug utilities and test media from master_staging
5. Push the updated branch to gitlab
> git push --force-with-lease origin merge_staging
Why --force-with-lease? • Because master_staging has a different history from merge_staging, Git requires a "force" push. • Plain --force blindly overwrites the server. • --force-with-lease is the safety-enhanced version: it will only overwrite the server if no one else has pushed unexpected commits to origin/merge_staging in the meantime. 6. Make sure the builds complete on gitlab, perform the testing. 7. Revert merge_staging back using the tag once testing is complete: BE AWARE! tags are distinct from branches, if you forgot the name of the tag you made you can use:
> git tag
> git tag -n
to see information on a specific tag use:
> git show merge_staging_backup
> git checkout merge_staging
> git reset --hard merge_staging_backup
Verify the restoration:
> git log -1 --oneline
Expected output:
43996b0 feat(decision_tree): enhance simulation CLI with interactive and batch modes
8. Push the restored state back to GitLab:
> git push --force-with-lease origin merge_staging
9. Switch back to master_staging:
> git checkout master_staging
10. (Optional) Delete the temporary backup tag:
> git tag -d merge_staging_backup
Deleted tag 'merge_staging_backup'

Cherry pick merge request [^]

Problem: we add something to merge staging but we don't want to merge in everything, only that specific change we've made. 1. find the commit hash of the commit on staging
> git log
copy the hash, e.g: 832cdd9ce0f12ba57dae2eac74d7aad6c2d5bfb0 2. change to the branch you want to create the merge request into and pull latest changes:
> git checkout master
> git pull origin master
3. Create a new branch off the master branch for the merge request.
> git checkout -b update-docker-compose
4. Cherry pick the commit we want
> git cherry-pick 832cdd9ce0f12ba57dae2eac74d7aad6c2d5bfb0
x1@Normans-Mac-mini:~/projects/matoha-smartbench$ git cherry-pick 832cdd9ce0f12ba57dae2eac74d7aad6c2d5bfb0
Auto-merging docker-compose.yml
[update-docker-compose 89a2144] Removed deploy policy from docker compose to prevent container restarts on unclean shutdowns
 Date: Mon Jun 1 09:39:57 2026 +0100
 1 file changed, 13 insertions(+), 48 deletions(-)
5. Push the new branch to the master.
git push origin update-docker-compose
6. Create the merge request on github/gitlab

Sync local commits with remote when remote has moved ahead (Conflict-Safe) [^]

Problem: You have local commits on your branch. Meanwhile, commits have landed on the remote branch. You need to combine both without getting trapped in merge conflict hell. Rule 1: Never do a blind "git pull". Always fetch and inspect first. 1. Stash any uncommitted dirty files:
> git stash
2. Create a safety backup branch of your exact current state:
> git branch backup-wip
(Zero-cost safety net. If anything goes sideways, your work is 100% recoverable.) 3. Fetch remote updates without touching your working tree:
> git fetch origin <branch_name>
4. Inspect the divergence:
# See what they added that you don't have:
> git log --oneline HEAD..origin/<branch_name>

# See what you added that they don't have:
> git log --oneline origin/<branch_name>..HEAD

# Check which files both sides touched (potential conflict zones):
> git diff --stat HEAD...origin/<branch_name>
5. Combine the changes: Option A: Standard Merge (Recommended when you have multiple local commits) Resolves all conflicts in ONE single pass rather than repeating for each commit:
> git merge origin/<branch_name>
If conflicts occur: - Run "git status" to see conflicted files ("both modified"). - Open files, search for "<<<<<<<", resolve the logic. - If it's a huge mess and you want to bail out cleanly:
> git merge --abort
(Instantly resets your branch to before the merge started). Option B: Rebase (Cleaner history, best for 1-2 small local commits)
> git rebase origin/<branch_name>
If conflicts occur during rebase: - Fix conflict in the file. - git add <file> - git rebase --continue - To bail out completely:
> git rebase --abort
6. Verify tests and build before pushing:
> pytest
> git status
7. Push to remote:
> git push origin <branch_name>
8. Clean up:
> git stash pop             # restore uncommitted edits if stashed in step 1
> git branch -D backup-wip   # delete temporary safety branch once verified
Understanding git history ========================= History in Git is structured as a Directed Acyclic Graph (DAG). In graph theory terms, this means that each commit is a vertex (or node) while the parent-child relations that connect them are edges. An interesting note is that the direction of the edges are directed backwards in time such that Child commit --> parent commit. In any directed graph $G = (V, E)$ an edge is an ordered pair $(u, v)$ that represents an arrow between two vertexs $(u \rightarrow v)$. Based upon the number of edges coming in to or out of a vertex $v$, we can define the in-degree $(deg^{-}(v)$ and out-degree $(deg^{+}(v)$. The DAG structure of git history means that commits may categorized into the following classes based on the number of children or parents. Commit type out-degree (n_parents) in-degree Meaning Root commit: 0 - Initial commit Standard commit: 1 - Linear commit Merge commit: 2 - Merge 2 branches Octopus Merge ≥ 3 - merge 3 or more branches Leaf / Tip 0 tip of the branch (e.g. most recent commit) Linear Node 1 one commit exists on top of the current commit Fork point ≥ 2 multiple branches or commits originate from current commit -------------------------------------------------------------------------------------------------------------------------------------------- To view commit information for a given commit one can run > git cat-file -p 454fc72 tree 19fceb549c68864ecc73c563267302b7ebbb0cfb parent b2f0fe98d73f65ed45c720c17c014ac75fbda96d author Norman Khan 1792399970 +0100 committer Norman Khan 1792399970 +0100 The above shows a commit that has 1 parent and thus is a standard commit as per the table above. Looking at another commit with multiple parents (merge commit) shows that it can have two parents: > git cat-file -p 0edf946491f02ba41906b95c5ac005be45c71870 tree 614a84d98375c3d38902e751fed9505d16477a9e parent 45fc4daa782409bc944bf625b35615ab8388b67e parent 707b1a817e89b7f893814bf44781e0a713a27d4b author Tanisha Hisariya 1791899185 +0100 committer Tanisha Hisariya 1791899185 +0100 live garmnet dteection added One parent is the branch into which the commit was merged INTO while the other commit is the commit from which the branch was merged <-- I think this is wrong! Another useful command is git show --stat which shows for a specific commit shows the number of lines that were changed per file for that commit. > git show --stat 0edf946491f02ba41906b95c5ac005be45c71870 Merge: 45fc4da 707b1a8 Author: Tanisha Hisariya Date: Tue Oct 13 14:46:25 2026 +0100 live garmnet dteection added dev.sh | 79 ++++++++++++ docker-compose-dev.yml | 256 ++++++++++++++++++++++++++++++++++++++ docker-compose.dev.yml | 101 +++++++++++++++ docker-compose.yml | 39 +++--- smartbench/app_gui/Dockerfile | 9 +- smartbench/app_gui/blocks/camera_block.py | 4 + smartbench/app_gui/blocks/results_block.py | 24 +++- smartbench/app_gui/blocks/title_block.py | 1 - smartbench/app_gui/camera_capture/basler_capture.py | 55 +++++---- smartbench/app_gui/camera_capture/camera_manager.py | 22 ++-- smartbench/app_gui/camera_capture/camera_worker_thread.py | 18 ++- smartbench/app_gui/camera_capture/test_basler_capture.py | 12 -- smartbench/app_gui/camera_capture/test_camera_capture.py | 1 - smartbench/app_gui/camera_capture/test_camera_manager.py | 18 +-- smartbench/app_gui/deepstream_processor.py | 220 ++++++++++++++++----------------- smartbench/app_gui/example_ocr_outputs.txt | 11 ++ smartbench/app_gui/garment_detection.py | 458 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ smartbench/app_gui/kafka_handler.py | 18 ++- smartbench/app_gui/label_frame.py | 72 +++++++++++ smartbench/app_gui/main_gui.py | 127 ++++++++++--------- smartbench/app_gui/ocr_worker.py | 11 +- smartbench/app_gui/test_main_gui.py | 23 ++-- smartbench/data_manager/data_manager.py | 75 ++++++++--- smartbench/data_manager/decision_tree/rules_test.json | 279 +++++++++++++++++++++++++++++++++++++++++ smartbench/label_printer/test_data_payload.py | 22 ++-- smartbench/matoha_kafka/test_matoha_kafka.py | 5 +- stop_all_containers.sh | 1 + 27 files changed, 1646 insertions(+), 315 deletions(-) The graph structure can be visualized in cli using: > git log --graph --oneline --decorate -n 25 0edf946491f02ba41906b95c5ac005be45c71870