Cogito ergo non sum git


I am a Software Engineer and Clinical Social Worker based in San Francisco, CA | contact me or follow me.

Share

translation: “I think, therefore, I am not a git”

It has now been almost 10 months since I've been consistently using git with github.com, so I thought I would share my top pointers and lessons that have helped enhance my git experience so that you do not become a git when using git. The lessons are organized by these categories: speed up your work, find a workflow, debugging tips, and tips for early beginners.

Speed up your work

Can that be automated?

(0) Simplify Login: If you have typed in your username and password too many times and are ready for a change, use password caching and ssh.

Password Caching with timeout of 3 years (or until you restart your OS):

$ git config --global user.name [YOUR_NAME]
$ git config --global user.email [YOUR_EMAIL]
$ git config --global credential.helper 'cache --timeout=99999999'

If you would like to manually perform these steps, simply add the following code your ~/.gitconfig file:

$ cat ~/.gitconfig
[user]
        name = YOUR_NAME
        email = YOUR_EMAIL
[credential]
        helper = cache --timeout=99999999

For more detailed instructions on how to setup SSH or password caching, visit: github ssh protocol & https password caching

(1) Stay Organized: I organize my local repositories with the same path that github.com uses. This helps prevent nested repositories, speeds up my ability to find repositories, and distinguishes my forked repositories from another user's version. Also, you may find that this order helps you understand import statements in certain languages such as go.

All my repos are in this path:

~/github.com/[USERNAME]/[REPO]

This is the same path as the URL:

https://github.com/[USERNAME]/[REPO]

(2) Set your default editor: You don't have to keep using nano as your default git editor. I prefer emacs:

$ git config --global core.editor "emacs"

Or, you can add this section to your ~/.gitconfig file:

$ cat ~/.gitconfig
[core]
	editor = emacs

Find a workflow

merge conflicts!

(3) Branches: I like the branch system, which has taught me to always specify the repository, either local or remote and the branch that my commands refer to. Therefore, I never run a plain $ git push nor any other $git command without specifying the branch. Instead, I might run command like $ git push origin master, or $ git log master. This practice has helped me with my understanding of the differences between local and remote (i.e. origin) repositories, as well as the differences in branches. It is also essential for when I began working with other branches because many commands have a default behavior for when there is no branch specified. For example, do you know what the default behavior for $ git push and $ git log? Will you want to restrict yourself to these behaviors every time you run these commands?

(4) gitflow & oneflow: To help me with the branching system and workflow I became familiar with 2 main git workflows. "gitflow" and "oneflow". I personally prefer "oneflow" when it is recommended. Oneflow's model is to always keep one workflow always merging into master, creating releases at major product releases. You can learn about it from, OneFlow - a Git branching model and workflow, an article by Adam Ruka, currently a full stack software engineer at Amazon. But if you are on a team that prefers gitflow, you should read, A successful git branching model, by Vincent Driessen, currently CTO of GitPrime.

(5) Rebase: Since working with various branches, I don’t ever run $ git pull. I started this because I like a clean commit history. Using $ git pull could add an unnecessary merge, which adds a commit. Often, this results in losing previous commits in the branch and version you are working with because they are replaced with the merged commit. The unnecessary merge commit will look something like this in the commit history of the master branch:

Merge branch 'master' of https://github.com/[THE USERNAME AND REPO]

Why merge branch ‘master’ to ‘master’? More details on why $ git pull can be problematic can be viewed in the Stack Overflow question: Git pull results in extraneous “Merge branch” messages in commit log (see the answer that is a revision of the top answer). Instead, the below commands will get the local repository and branch that you are working on up to date with any remote changes, while preserving the commit history, and ensuring that any other commits stay in the proper place (instead of being replaced with an unnecessary merge):

With No Local Changes:

$ git fetch origin [BRANCH]
$ git reset --hard origin/[BRANCH]

With Local Changes:

$ git fetch origin [BRANCH]
$ git rebase origin/[BRANCH]

Debugging Tips

Coding so hard your head hurts

(6) Amend HEAD commit: $ git commit --amend is helpful because it allows me to rewrite the most previous commit in case any updates in my code since that commit do not require a new commit message. To rewrite a more previous commit, see below: (7) Rewrite History.

$ git commit --amend
  • This command opens up an interactive editor with the most recent commit message.
  • Change the message to what you want it to be, then save/quit. Any other additions you have made and added will be added to the most recent commit.
  • It should be executed after $ git add ....
  • If the commit that you overwrite is already pushed to a branch on the origin repository, then you will have to run $ git push --force origin [YOUR BRANCH].
  • Note: if you are making a force push be very careful because you will overwrite the repository you are pushing to. Be sure to make backups if you are unsure of what you are doing.

(7) Rewrite History: For major mistakes or to cleanup and to rewrite multiple commits, I like: $ git rebase --interactive HEAD~[NUM]. Many git users will recommend not to use this command, but it exists for a reason, so if you have made some major mistakes, you can utilize its power.

$ git rebase --interactive HEAD~[NUM]
  • This command opens up an interactive editor with the most recent 'NUM' commits.
  • Next to each commit, there will be the message "pick". To remove this commit message, replace "pick" with "squash". This removes the message and adds the saved code updates to the next previous commit before the squashed commit. Since changes are added to previous commits, you cannot squash the most previous commit from the interactive mode.
  • Note: Use “reword” instead of “squash” to simply change a message from a previous commit.
  • Then, save/quit, which will open another interactive editor.
  • You can optionally write a message in the bottom of this editor or write one comment to replace all of the squashed comments.
  • Then save/quit again.
  • Finally, run $ git push --force origin [YOUR BRANCH], to add these changes to another origin repository.

(8) Diff check and history log: You can always create a new branch, and push it to the origin to compare and understand the git history:

$ git checkout -b [NEW_BRANCH_NAME]
$ git push origin [NEW_BRANCH_NAME]

To view the differences between your changes and the master branch, check out the commit history in the github.com interface or in the command line:

$ git log --pretty=oneline origin/master
$ git log --pretty=oneline [NEW_BRANCH_NAME]

Or use git's diff command:

$ git diff origin/master [NEW_BRANCH_NAME]

This will help you understand any changes that you have made and orient you to your work history.

(9) Restore latest saved version of a file: If you are not satisfied with a range of updates to one or many files, you can always restore your entire branch or just one file to the state it was in from the most recent commit. The below commands will be executed on the files or branch that you are currently working on (to verify the branch type git branch); they throw away all changes on the selected files restore those files to the state they were in from the most recent commit of the branch specified in the command. If no branch is specified in the command there is a default behavior for the changes to be applied to the current working branch:

Restore 1 file at a time:

$ git checkout [BRANCH_NAME] [FILE_PATH]

Restore entire branch:

$ git reset --hard [BRANCH_NAME]

Tips for early beginners

The Freshman

(10) Experiment: Don't be afraid to experiment with git commands, which can be a major part of any learning process. If you don't know what something does, try it out to see what happens. Since we are working with software, we can create backups, and we can always restore it locally or in the cloud repository at github.com in the event that we click a doomsday device.

(11) RTFM: Try using the long form of the flags of your commands $ git commit --message '...'. Know what the commands do. E.g. $ git add . -A adds any changes, deletes or additions, to be queued for $ git commit. commit is equivalent to saving your changes into the branch history and version. Finally, have you read the man page yet?

$ man git
Posted in code, github, linux and tagged , , .