Skip to content

Common Git Command Sequences

Marc edited this page Mar 11, 2024 · 2 revisions

(Re)Create a fresh copy of the repository

Use the git clone command to obtain a fresh copy of the repository. Note that you will obtain all branches and the full history of the repository.

# Clone the repository: It will create a `khiops` directory in your current location
git clone ssh://github.com/KhiopsML/khiops.git

# Re-install pre-commit scripts to run code formatting, static analyses, etc. before each commit
pre-commit install
  • You can also force a pre-commit: pre-commit run --all-files

Getting the Status of Your Local Repository

The git status command shows you useful information such as:

  • The current branch
  • Whether the current branch synchronized with Github's copy
  • Which files have changes ready for the next commit ("staged" files, in green)
  • Which files have changes (in red)
  • Which files are not in the repo (those in the .gitignore file are ignored, in red)
  • Hints for commands to make specific changes (eg. git restore)

During git rebase and git merge, git status also has specific information about the ongoing procedure.

Commit History (Log)

The git log command shows the list of commit messages.

# Complete log from the current commit
git log

# Complete log from a specific commit
git log <COMMIT-HASH>

# Complete log for a file (with diffs, from the current commit)
git log -p path/to/file

# Complete log for a file in gitk GUI
gitk path/to/file

# Complete log from the current commit with only the commit message titles
git log --oneline

# Last 4 commits from the current on
git log -n4

# Show Log in gitk GUI
gitk

# Shows a graph of the entire repo
git log --graph --decorate --pretty=oneline --abbrev-commit --all

Basic Branch Management

Branches are pointers to specific commits. They auto-update when committing so they always point to the tip of the branch.

# To see all branches in the local copy of the repository
git branch --all

# To switch to another branch
git switch branch-name

# To create and switch to new local branch
git switch -c new-branch-name
# Note: The new branch starts from tip of the current branch. After the operation both branches
#       point to the same commit.

# To delete a branch in your local repository (-D to force (!))
git branch -d branch-name

# To copy a newly created branch to Github (ie. `origin`)
git push --set upstream origin new-branch-name

Committing

Commits are made in two steps. First you decide which changes go in the commit and then you "execute" the commit and add its message.

Commits should be as atomic as possible, while being not too small to be linked to a consistent minimal update.

Prepare the changes for a commit (aka. staging changes)

To prepare a commit you must manually decide which changes go in it. This procedure is known as staging as the changed are files added to the staging zone or index.

Use git status all along this process to see which changes are taken into account for the next commit (see above).

# To stage all changes
git add -u

# To stage the changes of a specific file
# OR
# To add a new file to the repo
git add path/to/file

# To rename a file (it auto-stages)
git mv path/to/file new-path/to/new-file

# To remove a file from the repo (it auto-stages)
git rm path/to/file

# To see the difference of the staged files with respect to the last commit
git diff --staged

# To unstage a staged file
git restore --staged path/to/file

# To discard all changes in a non-staged file
git restore path/to/file

Note that any command that accepts paths also accepts globs (eg: git add path/to/dir/*).

Commit the changes to your local repo

Standard case

Once you have all the changes staged execute

git commit

This will trigger the pre-commit scripts. If they fail they usually change the offending files, so you can stage these new changes with git add -u and then git commit.

Once the pre-commit scripts pass, your configured text editor will pop up to write the commit message. The commit message structure is as follows:

  • the first line is the title, and it should short explaining the What the commit does
  • followed by an empty line (without this the full message will be title!)
  • then detailed comments if necessary, usually with an explaining the Why, How and more details about the What of the commit.
  • good practice: check your changes to write a synthetic summary
    • With your IDE, or
    • with git diff --staged before committing

Common Variants

# To commit with only a title. It doesn't open the text editor
git commit -m'My message'

# To fix the last commit with your current staged changes (eg. a typo)
git commit --amend

# Same as above, but without editing the commit notes
git commit --amend --no-edit

# To skip the `pre-commit` checks.
git commit --no-verify

Updating the Central Repository

Once you have committed one ore more changes you may want to update the central repository (GitHub). To do this, in your branch execute

git push --force

Warning: Make sure that you are working alone in the branch you are pushing. If it isn't the case you may use the safer option git push --force-with-lease which will fail if there are commits of other users in the central's repository version of the branch.

Using the Central Repository for Temporary Backups

You don't need to update the central repository only when your branch is in a stable state. To mark intermediary states you may create WIP (work in progress) commits that you push to the central repo periodically (eg. at the end of the day). Usually the notes of these commits do not contain too much information (eg. WIP Step 1 or WIP: Refactor CI). Don't be shy about creating WIP commits as you can clean the branch later by squashing.

Once your changed are OK to be merged you need to squash the commits. To do this you perform an interactive rebase.

# Look up for the hash of root commit to rebase, usually that preceding the base of squashing commit
git log --oneline

# Once found
git rebase -i <HASH>

# Alternatively you can take `dev` as your root commit
git rebase -i dev

Warning: Do not rebase to a commit before the branching point of your branch

This will prompt your editor with a screen like the following

pick d551adc5 WIP Step 1
pick 4e849846 WIP Step 2
pick 489e2913 WIP Step 3

# Rebase 870bb29b..4e849846 onto 870bb29b (3 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup [-C | -c] <commit> = like "squash" but keep only the previous
#                    commit's log message, unless -C is used, in which case
# ...
# <MORE VERY USEFUL INFORMATION>

The screen shows a list of operations are commits from the oldest to the most recent.

Note: If you don't change anything or don't save anything or you save an empty file the operation is aborted.

Now to squash the WIPs:

  • identify the first WIP commit
    • in the example d551adc5
  • change ganything below the previous commit from pick to squash or s
    • in the example we change pick 4e849846 WIP Step 2 to squash 4e849846 WIP Step 2 and pick 489e2913 WIP Step 3 to squash 489e2913 WIP Step 3
  • Save the file and exit the editor

This will trigger the squashing of the selected commits and prompt your text editor to modify the notes of the squashed commit

# This is a combination of 2 commits.
# This is the 1st commit message:

WIP Step 1

LearningTestTool: debut de la prise en compte de argparse

# This is the commit message #2:

WIP Step 2

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# ...
# <MORE VERY USEFUL INFORMATION>

Edit this like to a proper commit message so the squashed. The operation will transform the squashed commits into a single one by applying to the base commit the subsequent ones.

You then may update the central repo with a git push --force.

Merging to dev

Creating Pull Requests

You may create a pull request for your feature branch once it has at least a commit. This may be useful to trigger basic tests while you are in a WIP state.

However, the pull request will not be ready to be merge until:

  • Your feature branch is rebased to the latest version of dev (see below)
  • The CICD tests and checks are OK (green)
  • For major changes or new features the LearningTest end-to-end tests to pass

When you finish your work in a feature branch a pull request is necessary to Prerequistes:

  • first, rebase your branch branch on dev to get the last version of the source
  • tests on the standard family will be carried out automatically using CICD

Rebasing to dev

Before merging a feature branch to dev it is necessary that the feature branch is rebased to dev. This is to resolve potential conflicts before merging and having a more linear commit history.

# Update `dev` branch
git switch dev
git pull

# Rebase your branch
git switch branch-name
git rebase dev

In case of conflicts the rebase will stop and ask for a resolution. git status will show which files are in conflict. You may do the resolution in your IDE or with a simple text editor. Once solved you can continue the rebase by executing

git add -u
git rebase --continue

If anything goes wrong: git rebase --abort.