# Git / GitHub usage cheatsheet ## Shallow Clone ### method 1 Carefully clone what you need (without cloning large amount of old history data). In GIT, you can determine number of commits to download from remote repo. ``` cd NEW_FOLDER git init ``` * Use [remote](https://git-scm.com/docs/git-remote) to specify which branch of remote repository your local codebase should synchronize with ``` git remote add -t <EXISTING_REMOTE_BRANCH> <ALIAS_NAME> <GIT_REPO_URL> ``` where - `<EXISTING_REMOTE_BRANCH>` : branch name created at remote repo - `<ALIAS_NAME>` : alias name of the remote git repo, referenced at local git repo e.g. ``` git remote add -t my_remote_master local_origin_123 https://my.github.codebases/project123 ``` To fetch codebase at specific commit without loading all older commits in the same branch. * Note this command will generate [detached branch](https://stackoverflow.com/questions/10228760/how-do-i-fix-a-git-detached-head) * If you also want to switch between different tags, ensure you have enough commits in the `git fetch` command (that means, `--depth` should be large enough so you can switch to specific commit / tag later in `git checkout` command) ``` git fetch --depth <NUM_COMMITS> <ALIAS_NAME> <COMMIT_SHA1> git fetch --depth <NUM_COMMITS> <ALIAS_NAME> tag <EXISTING_TAG_LABEL> ``` where - `<NUM_COMMITS>` indicates number of consecutive commits to fetch, starting from the commit represented as `<COMMIT_SHA1>`, going back to the nth. old commit - `<ALIAS_NAME>`: name of the remote git repo, previously created on `git remote add` - `<EXISTING_TAG_LABEL>` indicates existing specific tag label in remote git repository. ### method 2 clone number of commits from main branch of a git repository ```bash git clone --depth <NUM-COMMITS-FROM-HEAD> ``` ## Branch ### List existing branches of current repo ``` git branch ``` ### Create a new local branch under current local repo ``` git branch <LOCAL_LABEL> ``` Note: - local branches may be different from remote branches in the same repo - For [Shallow Clone](#shallow-clone) where a default [detached branch](https://stackoverflow.com/questions/10228760/how-do-i-fix-a-git-detached-head) is created, it is a good practice to create other local branches (e.g. one for backup, others for new patches) before you move on and change the codebase. - Once you switch from detached branch to any other branch (by `git checkout <EXISTING_LOCAL_BRANCH>`), the detached branch will disappear, it is better NOT to change the code under detached branch. ### check commit history under specific branch ```bash git log <EXISTING_LOCAL_BRANCH> ``` ### Switch between commits Consider `commit` as single node of an arbitrary tree structure, you can switch between them back and forth using [git-checkout](https://git-scm.com/docs/git-checkout). ``` git checkout <COMMIT_LABEL> ``` where the `<COMMIT_LABEL>` could be one of followings: |syntax|meaning| |------|-------| |`FETCH_HEAD`|to the latest commit of current branch| |`<SHA1_HEX_STRING>`|SHA1 string, represent the specific commit| |`<TAG_NAME>`|to specific tag| |`<EXISTING_LOCAL_BRANCH>`|to specific local branch| ## Push Update change to remote repo with the command [git-push](https://git-scm.com/docs/git-push) Preresuisites : - switch to the appropriate [local branch](#branch) you want to update (source) - specify appropriate remote branch (destination) ```bash git checkout <EXISTING_LOCAL_BRANCH> git push -u <ALIAS_NAME> HEAD:<EXISTING_REMOTE_BRANCH> ``` where - `<EXISTING_REMOTE_BRANCH>` : branch name created at remote repo - `<ALIAS_NAME>`: name of the remote git repo, previously created on `git remote add` ## Cherry pick copy one commit from source branch to destination branch within a git repository. - possible use case - resolve conflict between branches , by applying a specific commit from one Git branch to current `HEAD` of another branch. - one has to ensure the commit to cherry-pick is small enough so it can be reused across branches in the repository. ```bash git cherry-pick <SHA-HASH-OF-COMMIT> ``` Note: - `<SHA-HASH-OF-COMMIT>` indicates SHA2 hash valud of the commit to pick. - switch to destination branch before the cherry-pick operation, so commit can be copied to right location. ## Merge ### Rebase ```shell! git rebase <upstream> [<target>] ``` Move base of a target branch `<target>` forked from another branch `<upstream>` in a git repository. - `base` in this context means the common latest commit existing in both sides of the branches. - this command requires the branch `<target>` is clean without uncommitted change , otherwise it reports error below : ``` error: cannot rebase: You have unstaged changes. error: Please commit or stash them. ``` - one workground is to temporarily save unstaged changes to git's internal stack by `git stash` After the commnad, the commits existing ONLY in branch `<target>` will be moved to `HEAD` of branch `<upstream>`. **Rebase example** : assume the branch `<target>` was forked on commit `B` , and both branches advanced with a few new commits. ```markdown A---B---C <upstream> / D---E---F---G <target> ``` After rebase, the commit chain `D,E,F,G` is moved to commit `C` , which is current `HEAD` of `<upstream>` ```markdown A---B---C <upstream> / D---E---F---G <target> ``` Reference : `git rebase --help` #### Resolve conflict during rebase **TODO** ### Squash **TODO** ## Misc ### show detail of specific commit ```bash! git show <specific-commit> --pretty=format:"" ``` - `<specific-commit>` could be hash of the commit or specific label such as `HEAD` - `--pretty=format:""` prints file content changed excluding summary message. ### submodule Link a sub git repository to specific path of another (main) git repository, [git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules) ```bash git submodule add https://URL.to.sub.repo /main-repo/path/to/dst ``` after this command, you can directly commit it, a file named `.gitmodules` will be automatically added to the main repository ### Tag List all tags which can be switched to in the local repository (depends on `--depth` in your previous `git fetch`) ``` git tag ``` ### pull partial commit history * Alternative #1 , `--depth` works the same way, `HEAD` indicates that the git starts from the latest commit and download specific number of commits (in this case it is `3`): ``` git pull --depth 3 <REMOTE_NAME> HEAD ``` * Alternative #2 , load all histories. It is not good for large-scale repositories (e.g. with millions of commits), because it may load unecessary old commits you've never used : ``` git clone --depth 1 <GIT_REPO_URL> --branch <BRANCH_NAME> ``` ### Remove local commit To remove local commit without discarding the change : * latest commit only ``` git reset HEAD^ ``` ### Stash Temporarily save uncommitted / unstaged / dirty changes to git's internal stack , the purpose is to keep working directory clean and match `HEAD` commit of current branch, this is required for certain git commands. ```bash! # save local dirty change temporarily git stash --message="Work-In-Progress : before rebase" # perform other git commands , such as rebase # restore back at later time git stash pop ``` ## TODO - [recover back to previous local commit status using `git reflog` and `git reset --soft`](https://chatgpt.com/share/681f074d-aa00-8003-93f8-ccbcea73b2e6) ###### tags: `Dev-tool` `Git`