git


#versioning #code #tool #infrastructure

Resources

Learning git

git checkout

Setup upstream and merge with fork/main

When you make a fork, you might want to track and merge commits from the upstream repo into your fork's main branch. To do so:

  # add the upstream/main as remote upstream
  git add remote upstream git@the_repo

  # fetch upstream
  git fetch upstream

  # merge upstream into main
  git merge upstream/main

  # resolve conflicts
  # then push to your own origin/main
  git push origin main

Rebase and squash

If you are using a forked repo, don't forget to update to latest upstream

# After updating your main branch
# use the interactive rebase command
git rebase -i main

This opens a todo file for the rebase in progress, in your EDITOR. You then have to pick the first commit into which you want to squash the other commits.

add af32ff1b12a1096f #your commit message
add 88d6c9bb26ffb381 #your second commit message
# ...

The file usually has instructions at the bottom on keywords and the associated action.

You can pick the commit into which you will squash the other commits.

pick af32ff1b12a1096f #your commit message
squash 88d6c9bb26ffb381 #your second commit message
# ...

Commit messages are then added in order, and can be interactively

Commits can be renamed with edit or after the rebase has been finishe, with:

git commit --amend

branching and merging - How to change current branch in git from master to main - Stack Overflow

  1. rename your local branch:

    git branch -m master main
    
  2. change the tracked branch

    git fetch -p origin
    git branch -u origin/master main
    
  3. change the main local branch

    git remote set-head origin -a
    
  4. optionally, remove the master branch, local and remotely:

    git branch -D master
    git push origin :master
    

Drop commit

Careful: git reset --hard WILL DELETE YOUR WORKING DIRECTORY CHANGES. Be sure to stash any local changes you want to keep before running this command.

Assuming you are sitting on that commit, then this command will wack it...

git reset --hard HEAD~1

The HEAD~1 means the commit before head.

Or, you could look at the output of git log, find the commit id of the commit you want to back up to, and then do this:

git reset --hard <sha1-commit-id>

If you already pushed it, you will need to do a force push to get rid of it...

git push origin HEAD --force

However, if others may have pulled it, then you would be better off starting a new branch. Because when they pull, it will just merge it into their work, and you will get it pushed back up again.

If you already pushed, it may be better to use git revert, to create a "mirror image" commit that will undo the changes. However, both commits will be in the log.


FYI: git reset --hard HEAD is great if you want to get rid of WORK IN PROGRESS.It will reset you back to the most recent commit, and erase all the changes in your working tree and index.

git stash does the same except you can restore it later if you need, versus permanently delete with reset hard mode. Check your stashes by using git stash list and git stash show 'stash@123'


Lastly, if you need to find a commit that you "deleted", it is typically present in git reflog unless you have garbage collected your repository.


Git Branch Management and History Cleanup Guide

Overview

This guide covers common Git workflows for managing branches, cleaning up commit history, and preparing branches for pull requests. These techniques help maintain clean, organized version control history.

Separating Mixed Commits into Different Branches

When you have a single branch containing commits for multiple problems that should be separated:

# Create new branches from your mixed branch
git checkout your-mixed-branch
git checkout -b problem-1-branch
git checkout -b problem-2-branch

# Use interactive rebase to filter commits for each branch
git checkout problem-1-branch
git rebase -i HEAD~n  # where n is the number of commits to review
# Delete lines for commits that belong to problem 2

git checkout problem-2-branch
git rebase -i HEAD~n
# Delete lines for commits that belong to problem 1

Method 2: Cherry-picking

# Create clean branches from before mixed work
git checkout <commit-before-mixed-work>
git checkout -b problem-1-branch
git checkout -b problem-2-branch

# Cherry-pick relevant commits to each branch
git checkout problem-1-branch
git cherry-pick <commit-hash-1> <commit-hash-3>

git checkout problem-2-branch
git cherry-pick <commit-hash-2> <commit-hash-4>

Resetting Master Branch to Origin

When your local master branch has unwanted commits:

Basic Reset Process

# Backup current state (safety first)
git checkout master
git branch backup-master

# Fetch latest from origin
git fetch origin

# Reset to match origin/master
git checkout master
git reset --hard origin/master

# Verify the reset
git status
git log --oneline -10

If Origin Also Has Bad Commits

# Find the last good commit
git log --oneline

# Reset to that specific commit
git reset --hard <good-commit-hash>

# Force push to update origin
git push origin master --force-with-lease

Selective Commit Squashing

Use interactive rebase to selectively squash commits while ignoring others:

# Start interactive rebase
git rebase -i HEAD~n  # or git rebase -i <commit-hash>^

Available Commands in Interactive Rebase

Example: Selective Squashing

pick abc1234 Commit message 1      # keep as-is
pick def5678 Commit message 2      # this will be the base
squash ghi9012 Commit message 3    # squash into commit 2
pick jkl3456 Commit message 4      # keep as-is
pick mno7890 Commit message 5      # keep as-is

Alternative: Cherry-pick with Squashing

# Create new branch from clean point
git checkout -b cleaned-branch <base-commit>

# Cherry-pick and combine commits
git cherry-pick <commit1>
git cherry-pick --no-commit <commit2>  # stages without committing
git cherry-pick --no-commit <commit3>  # stages without committing
git commit -m "Combined commit message"

# Cherry-pick other commits normally
git cherry-pick <commit4>

Rebasing Branch on Updated Master

Before creating a pull request, rebase your feature branch on the latest master:

Standard Rebase Workflow

# Update master
git checkout master
git pull origin master

# Switch to feature branch and rebase
git checkout your-feature-branch
git rebase master

# Force push the rebased branch
git push origin your-feature-branch --force-with-lease

Handling Rebase Conflicts

# When conflicts occur during rebase:
# 1. Fix conflicts in your editor
# 2. Stage the resolved files
git add .

# 3. Continue the rebase
git rebase --continue

# If you need to abort the rebase
git rebase --abort

Interactive Rebase for Cleanup

# Rebase with ability to modify commits
git rebase -i master

Best Practices

  1. Always backup before destructive operations: Create backup branches before using reset --hard or force pushing
  2. Use --force-with-lease instead of --force: Safer when force pushing as it won't overwrite others' changes
  3. Keep commits focused: Each commit should represent a single logical change
  4. Rebase before creating PRs: Ensures clean, linear history on top of latest master
  5. Test after rebasing: Verify that your changes still work correctly after rebase operations

Safety Notes


Git Pull: Skipped Cherry-Pick Commits

Issue Description

When executing git pull, users may encounter a warning message about skipped commits that were previously applied through cherry-picking operations.

Example Output

git pull
warning: skipped previously applied commit 3a5eaa6
hint: use --reapply-cherry-picks to include skipped commits
hint: Disable this message with "git config set advice.skippedCherryPicks false"
Successfully rebased and updated refs/heads/fix_url_parsing.

Explanation

Warning Message

Hints Provided

Success Confirmation

Resolution

This warning is normal behavior and indicates successful operation. No action is required unless you specifically need to reapply the skipped commits.

git diff

Diff latest vs last commit

As the previous commit can be accessed with HEAD^, I think that you are looking for something like:

git diff HEAD^ HEAD

That also can be applied for a :commithash

git diff $commithash^ $commithash

As of Git 1.8.5, @ is an alias for HEAD, so you can use:

git diff @~..@

The following will also work:

git show

If you want to know the diff between head and any commit you can use:

git diff commit_id HEAD

And this will launch your visual diff tool (if configured):

git difftool HEAD^ HEAD

Since comparison to HEAD is default you can omit it (as pointed out by Orient):

git diff @^
git diff HEAD^
git diff commit_id

Warnings

  • @ScottF and @Panzercrisis explain in the comments that on Windows the ~ character must be used instead of ^.

Source: https://stackoverflow.com/questions/9903541/finding-diff-between-current-and-last-version

Back to the top ↑