# Git_Training ## Tricky commands Here are a few commands that you may not know yet, or that offer options you haven’t been aware of so far. ### git-stash `git stash` is something that can be incredibly handy. What it does is very simple: If you run `git stash save` it will take all the changes you have in your working directory and the index, and save them away, leaving you with a clean working directory. Once you’ve done what you wanted to do, you can restore your changes by running `git stash pop` But it gets better: since `git stash` saves your changes in a commit, you can stash more than once, and you’ll get a nice list of commits with your stashed changes. `git stash` will also keep track of what branch you stashed your changes on, so you’ll know later on what stashed change exactly you want to restore. `git stash list` will list all the stashes you’ve saved away, `git stash apply` will apply the topmost stashed commit onto your working directory, `git stash pop` will also remove the stashed commit in addition to applying it. `git stash clear` throws away all your stashes, and `git stash drop` allows you to remove a single stash. ### git-rebase `git rebase` can be a very tricky command, although its purpose is very simple: Given a range of commits as well as a starting point, it will port the given commits onto that starting point, preserving the commits themselves, but also allowing you to keep a linear history (that is, no merge commit). Most of the time you’ll give it just one ref: The branch you’ll want your current branch to rebase onto. `git rebase` then figures out where those two branches diverged, and use that as the beginning of the commit range. If you pass it a second argument, `git rebase` will first switch to that branch before porting your commits. It also has one very useful flag: `--interactive`. If you pass this flag, Git will launch your favorite editor with a list of all the commits it is going to rebase. All commits are prefixed with `pick` by default, but you can either drop commits entirely (just delete their line), reorder them to your liking, or `edit` if you’d like to edit or amend the commit (note that this also allows you to split commits), `reword` if you’d just like to change the commit message, and `squash` or `fixup` if you want to squash the commit with the previous one. `fixup` will reuse the previous commit’s message, while `squash` allows you to edit the new commit’s message. The interactive mode is very useful when you’re working on some idea you’ve had, make a commit, and later on realize that it isn’t quite working out that way. You commit a fix, but the commit it fixes is already buried in other commits, so you can’t simply amend. `git rebase --interactive` allows you squash those two commits together and make it look like you never made the mistake in the first place. ### git-push This is a command that you’re probably using often already, but it gained a few more useful options in recent versions: - `-u` or `--set-upstream`: When doing `git push local-branch:remote-branch`, you can use `-u` to tell Git to set up `remote-branch` as the default upstream branch, so you’ll only need to do `git push` in future. - `--delete`: Instead of pushing the specified refs, it will instead delete them from the remote repository. ### git-reflog Whenever an operation changes the tip of a branch, the Reflog mechanism records the old and new locations. `git reflog` allows you to access and manage this information. This is very useful and potentially life saving after any command that (seemingly) changes the history of your repository, like `git rebase` or `git filter-branch`. While these commands do indeed change commits, the old commits aren’t deleted, they are merely unreachable by normal means (This is also the reason why Git will occasionally run `git gc` on your repo). However, using the Reflog mechanism you can find out the SHA1’s of these commits, and restore them if you need to. `git reflog` lists all the recorded reflog information, and you can then specify any point in the reflog using the syntax `head@{0}` (where `head` is any kind of ref, and `0` to specify the very first reflog entry). For example, if you just did a rebase, but decided that you messed up somehow, you can restore your branch to its state before the rebase by using this command: ```bash git reset head@{1} ```