# Git Basics
## Creating a new repository
### Creating a new repository by starting on Github
1. Navigate to [`github.com/new`](https://github.com/new)
2. Create a new repository:
- [x] Add a README file (for now, this will be autofilled with the name of the repo and the description you give it)
- [x] Add `.gitignore` (use one of the templates provided by Github)
- [x] Choose a license (usually MIT)
3. Navigate to your newly created repository
4. Click the green `Code` dropdown and copy the URL under the `HTTPS` tab (this is also just the URL to the repository with `.git` appended)
5. Navigate to your desired **parent directory** (the directory *inside* of which your project will live) and open a terminal
6. Run `git clone <URL>` where `<URL>` is what you copied to your clipboard in step 4 -- this will automatically create a new directory for your project
7. Copy all of the files relevant to your project which you want to make public on Github into the project directory created by the command you ran in step 6
:::info
:information_source: **Note**
If there are any files in your project which you *do not want to make public, but do want to keep as part of the project,* add them to the `.gitignore` file. See instructions below for details.
:::
8. Run `cd ./<your project directory>` where `<your project directory>` will be the same as the URL you gave your project on Github (e.g., if you created a repository `/my-fancy-new-app`, that'll be the name of the directory that was created when you ran `git clone` in step 6)
9. After adding your project files to your local repository, run `git add .` -- this step is refered to as **staging your commit**
:::info
:information_source: **Note**
The command `git add .` is the lazy way to **stage** *everything* in your directory for commit. Sometimes this isn't desired behavior. You can always `git add my_file.ext` or `git add *.ext` to add the specific file `my_file.ext` or all files with the `.ext` extension, respectively. You can even `git add Subdirectory/` to add *everything* in the `Subdirectory`. See the [documentation](https://git-scm.com/docs/git-add) for more details (warning: Git's documentation is super terse).
:::
10. You can optionally run `git status` to check the status of your local repository (if you've added a bunch of new files or made changes to already tracked files, then you'll see a bunch of red file paths)
11. Run `git commit -m "<your commit message>"` where `<your commit message>` succinctly describes how *this specific commit* changes your repository (e.g. `"updates README"` or `"fixes excel file export bug"`)
:::danger
:heavy_exclamation_mark: **Danger**
If you forego the `-m "<some message>"`, Git will automatically open a text editor. Depending on how we set up Git for you intially, the text editor Git chooses for this task may be difficult to use. No matter what, you need a commit message. The `-m` flag makes it very easy to do add one.
:::
13. Run `git push` and you're done!
:::success
:heavy_check_mark: **Done!**
You've successfully **created** a repository on Github, **cloned** it to your `local` development environment, **added** your project files to your `local` repository, **committed** those new files for Git to start tracking, and **pushed** those files to the `remote` repository!
:::
### Creating a new repository by starting with a local repository
The other way to create a new repository is to use `git init` in an existing local project directory, creating a blank remote repository on Github (don't add README, `.gitignore`, or license), configuring Git (via the command line) to "point" your local repo to its remote counterpart, adding your files, committing, and finally pushing to the remote. [Github's tutorial](https://docs.github.com/en/get-started/importing-your-projects-to-github/importing-source-code-to-github/adding-an-existing-project-to-github-using-the-command-line#adding-a-project-to-github-without-github-cli) for doing this is well written (make sure **not** to follow any instructions involving the Github CLI, unless you want to install and use that tool).
The only real consideration when creating a new repository is whether you want the convenience of adding the license, README, and being able to use Github's `.gitignore` templates.
## General repository creation
Here's a more abstract explanation of each step in the repository creation process:
1. **Initialize** a repository -- either via `git init` (a brand new repository) or `git clone` (a repository that exists on a remote server like Github)
2. **Stage** files (`git add`) for commit
3. **Commit** changes (where "changes" refers to *any change in the state of the repository,* e.g., new files, edited files or deleted files that were previously tracked)
4. **Push** changes -- this step is purely related to telling your remote repository that something has changed locally and that you want those changes reflected on the remote server
## Updating a repository
Any time you add new files, or change tracked files (a file becomes "tracked" by Git whenever you `git add` it and then commit it), you will need to have Git tell your remote repository on Github that something has changed. All you really need to do is steps 9 through 13 in the guide above.
1. Open a terminal inside your project directory
2. Run `git add .` or any variation of `git add` to **stage** your files for commit
3. Run `git commit -m "<commit message>"`
4. Run `git push`
:::success
:heavy_check_mark: **Done!**
You've successfully **staged** new changes to your `local` repository, **committed** those changes, and **pushed** those changes to the `remote` repository.
:::
## Branching
If you want to try something new out like a big refactor, or adding a new feature to an existing script/app, the best way to do this would be to create a **branch**. A branch is a copy of the state of your repository at the time of branching. Branching allows you to make a giant mess *without affecting the working version of your code.* You could delete your entire app on a branch, and it wouldn't affect the `main` branch at all!
### Creating a new branch
1. Open a terminal in your project directory
2. Run `git branch <new-branch-name>` where `<new-branch-name>` is what you want to call your branch
:::info
:information_source: **Note**
A typical convention is to use a filepath-like branch naming structure (using slash-delimited hierarchies of description). For example, if you're adding a new feature, you might do something like this:
```
git branch feature/my-fancy-new-feature
```
If you want to work on a particularly nasty bug (one in which fixing it may involve breaking a lot of other things and which may require refactoring), you might do something like this:
```
git branch bugfix/excel-export
```
Branch names are conventionally written in kebab-case (hyphenated lowercase words) and should be as succinct as possible (because you'll need to type them out in the terminal whenever you want to work on them).
Someday, you might even need to work on a *branch of a branch*, in which case you'd continue the filepath-like structure of your branch names, e.g.:
```
git branch bugfix/excel-export/file-extension-errors
```
:::
3. Run `git checkout <name of branch>` where `<name of branch>` is the name of the branch you just created, for example:
```
git branch feature/bulk-file-upload
git checkout feature/bulk-file-upload
```
:::success
:heavy_check_mark: **Done!**
You've successfully **created** a new branch, which tells Git to make a new copy of your repository, then you **checked out** the new branch, which tells Git to pay attention to and attribute any further changes in your repository to that checked out branch (until you change branches again).
:::
### Switching branches
To switch to a different branch, simply run `git checkout <branch>` where `<branch>` is the name of the branch you wish to checkout.
:::warning
:warning: **Warning**
In order to checkout a branch, all changes on your current branch must either be [stashed](https://git-scm.com/docs/git-stash), or committed.
You can think of checking out a branch as analogous to checking out a book at a library that only lets you check out one book at a time. In order to checkout a different book, you'd need to go back to the library and return the one you're using.
By stashing any changes on a current branch before checking out another branch, you are essentially putting a bookmark in the book you're returning to the library, since you have, in essence, not finished your book (by not committing your changes).
Maybe the library analogy is a little weak...
:::