---
# System prepended metadata

title: Git / GitHub usage cheatsheet
tags: [git, Dev-tool]

---

# 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`
