# WORKING ON A FEATURE
## Creating new feature branch out of the master/development branch
1. Create branch out of master
```git
git checkout master
git checkout -b yourName-projectName-taskName
```
2. Adding appropriate prefix
Also, you should add appropriate prefix before the branch name
feature/..
fix/..
3. Pushing the new branch to the remote origin
```git
git push -u origin prefix/yourName-projectName-taskName
```
## Squashing commits before rebase
```git
git rebase -i {hash} # to squash all commits, where the oldest one is {hash}
```
## Rebasing parent branch
```git
git pull --rebase -i origin branchName # to get new changes from the remote repo and rebase
```
Resolve if any conflicts, and continue
```git
git rebase --continue
```
Force push changes
```git
git push -f
```
## Merging back into parent branch
```git
git checkout master
git merge -X theirs featureBranch
```
# EXPLAINED GIT COMMANDS WHEN WORKING ON A NEW BRANCH
Two options will be reviewed:
- **Rebase** - applies all of the parent (or other specified) branch commits onto
your branch. This moves your branch to begin on the tip of the rebased branch,
effectively incorporating all of the new commits in specified branch.
Use it when you are working on a feature, and needs to get fresh changes occasionally.
- **Merge** - merges your changes into the specified branch, also it creates new merge commit.
Use it when you are done with changes, and need to merge your branch back to the parent branch.
**NOTE**: You should only merge your branch, when you are done with all changes,
and it is up-to-date with the branch you are merging.
### PROBLEM ###
Let's say we have the following situation:
1. We create 'feature-x' branch out of 'master' branch
2. We did 30 commits that modifies file1, file2, etc.
2. Other developers also made 30 commits on 'master' branch modifying file1, file2, etc.
6. You will now want to update your branch with fresh commits from master
in order to continue working on a feature.
What will happen is, you will need to review every conflict in those 30 commits,
where the similar things were changed.
### SOLUTION ###
**Squashing**
You will need to squash all commits made since you created branch,
in order to get the new updates. Always use interactive squashing,
because it gives you the most control.
You can choose what to do with the specific commit: squash, delete, pick, fixup, etc.
In simple cases, it is enough to give squash (s) to every commit, except the first one leave it on pick (p).
You got few **options** when using rebase:
- Give hash value of the commit if you want to rebase every commit since that commit, except the given commit
- Give HEAD~2 if you want to rebase last 2 commits.
```git
git rebase -i {option} # to squash commits
```
**Rebasing**
You will need to rebase on a branch (usually parent - master)
```git
git rebase branch # rebase if local version of the branch is up-to-date
git pull --rebase -i origin branch # to get new changes from the remote repo and rebase
```

**Update**
After you finished with rebasing, force update the remote repository, since you
will have different commmits locally and remotely
```git
git push -f
```
*BE AWARE*: Don't do it if you are not sure what you are actually doing. This overrides
the remote branch with your local changes.
### Resolve conflicts (automatically)
If you rebase a branch feature-x against master
i.e. running: git rebase master
while on branch feature-x, during rebasing, ours refers to master and theirs to feature-x.
- Rebase preferring current branch (feature-x) changes merge during conflicts
```git
git rebase -Xtheirs master
```
After this step, always rebuild the code, to see if something wrong was done.
### THEIRS AND OURS (Merge vs Rebase)
Theirs and Ours behave differrently in merge than in rebase, they are reversed
due to the differences on how git rebase and git merge operate
assuming feature-x is our current version
```git
git rebase -Xtheirs feature-x # <- ours: feature-x, theirs: master
git merge -Xtheirs feature-x # <- ours: master, theirs: feature-x
git merge -Xours origin/master
```
## THE GOLDEN RULE OF REBASING
Never use it on public branches (master, development, staging, production, ...), use only on your emerged branch!
If you do git rebase feature-x during on master branch, the flow will look like this:

In this situation, only you will have
## RESET AND REVERT COMMITS
```git
git revert {hash}
git reset # Reverts and unstage changes
git reset --soft HEAD^6 # Does not touch the index file or the working tree at all
git reset --soft tags/v1.0.1
git reset --hard # Resets the index and working tree. Any changes to tracked files
in the working tree since are discarded.
git reset -- file # Suppose you have added a file to your index, but later decide you
do not want to add it to your commit. You can remove the file from
the index while keeping your changes with git reset.
<a href="https://git-scm.com/docs/git-reset#Documentation/git-reset.txt-Resetasinglefileintheindex" target="_blank" rel="noopener">Details</a>.
```
If you accidentially commit something, or you were not finished doing it,
you can do it in two ways:
1. **Hard reset** - removes commits altogether with files changed, they are gone.
```git
git reset --hard OPTION
```
It is preferably if you do git branch feature-y-copy before doing hard reset,
in order to keep commits.
Then do git push -f to force push local changes
2. **Reset (soft)** - points HEAD to the commit(s) and returns changes from commit(s)
in the stage so you can change and commit with different message etc.
```git
git reset OPTION
```
3. **Revert** - this will create another commit with deleted changes.
```git
git revert OPTION
```
**OPTIONS:**
HEAD^ - last commit
HEAD~X - last X commits
{hash} - every commit after this {hash} commit
# Q&A
1. Why not merge to get new changes from parent branch?
- Because it will create new commit every merge, and history log will look nasty.
With rebase, history will look clean and pretty.
2. I did a nasty mistake, and everything went wrong. What to do now?
- Use reflog. git reflog (--date=iso to get detailed timestamps) is reference log,
that keeps log of every step done via git command. It creates hash value
for every step or sub-step done with git. Just checkout the last working hash value
and you are good to go.
```git
git checkout {hash}
```
3. Discarding local changes and checkout remote branch
```git
git reset --hard origin/branchName
```
4. Detached state. What now?
```git
git push --origin <branch>
```
# TO BE CONTINUED...