DEV Community

Cover image for Git tricks 🚀 1/3
Facundo Botta
Facundo Botta

Posted on

Git tricks 🚀 1/3

Hi there! Today I want to share with you some cool git tricks that I recently learned from a book, “Aprendiendo Git & GitHub” (Learning Git & GitHub), and maybe it can be interesting to someone, and it's also a self-recap for me. I will split the post into three parts for a better reading and writing experience.

In this book, we can find many pieces of advice and mentions of the importance of key concepts in the Git world, like good commit messages, descriptive PRs, and more. But here, I only want to share some useful commands I’ve learned. I’m at a trainee/junior level, so don’t judge me too harshly if the topics here are basic to you! Maybe you’ll learn something anyway 🤣. So, let's go on...

Git config

git config allows to us to personalize somes core aspects of our git installation.

  • You can list your current config like this :
# To see all your config
$ git config --list
# To see only your global scope config
$ git congit --global --list
# To see your local scope config
$ git config --local --list
# To see your system config
$ git config --system --list

# You can add the --show-scope parameter to see the scope of any config
# only available from 2.26.0 version of git
$ git config --list --show-scope

# You will see something like this
# system  diff.astextplain.textconv=astextplain
# system  filter.lfs.clean=git-lfs clean -- %f
# system  filter.lfs.smudge=git-lfs smudge -- %f
# system  filter.lfs.process=git-lfs filter-process
# system  filter.lfs.required=true
# system  http.sslbackend=openssl
# system  http.sslcainfo=C:/Program Files/Git/mingw64/etc/ssl/certs/ca-bundle.crt
# system  core.autocrlf=true
# system  core.fscache=true
# system  core.symlinks=false
# system  core.editor=nano.exe
# system  pull.rebase=false
# system  credential.helper=manager
# system  credential.https://dev.azure.com.usehttppath=true
# system  init.defaultbranch=main
# global  user.email=myMail@gmail.com
# global  user.name=MyName
# global  safe.directory=C:/xampp/htdocs
Enter fullscreen mode Exit fullscreen mode
  • You can change some configuration like, for example, the default text editor…
$ git config --global core.editor "code"
Enter fullscreen mode Exit fullscreen mode

Here we tell Git that we want VS Code as our global default text editor instead of the nano editor. You can specify another scope or text editor if you want to.

  • An other interesting thing you can do is set a global gitignore
$ git config --global core.excludefile path_to_the_file/.gitignore_global
Enter fullscreen mode Exit fullscreen mode

Git checkout & git switch

We often use the checkout command to create and/or switch between branches in Git repositories.

It’s fine, but in fact, the checkout command is an old and powerful command that can do more things than just switching branches:

# Switch to a specific branch
$ git checkout <existing_branch_name>

# Create and switch to a new branch
$ git checkout -b <new_branch_name>

# Restore a file or many
# (Note: if you don't use the -- directive you are creating a new branch...)
# It will to restore the file to its state in the last commit
$ git checkout -- <file_1> <file_2> ...

# Restore a file to a specific commit state
$ git checkout <commit_id> -- <file>

# Switch to a specific commit
# Note: If you do this, you won't be on any branch. This state is called "detached HEAD."
# Any changes you make here can be lost because HEAD is not attached to a branch.
# To save your changes, you need to create a new branch from this point.
# In other words, you are not working on any branch at this moment.
$ git checkout <commit_id>

# Restore all the working tree
# It will to restore all to its state in the last commit
$ git checkout .
Enter fullscreen mode Exit fullscreen mode

As you can see, the checkout command can do many things, and we may be doing something that we actually don’t want to do…

To solve these potential confusions, Git introduced the switch command in version ≥2.23:

# Switch to a specific branch
$ git switch <branch_name>

# Create and switch to a new branch
$ git switch -c <new_branch_name>

Enter fullscreen mode Exit fullscreen mode

So to restore one o more files to the last commit state we have de restore command:

# Restore une o more files
$ git restore <file1>, <file2>
# Restore all working tree
$ git restore .
# Restore all files with js expension
$ git restore '*.js'
# Restore a file to a specific commit state
$ git restore --source <commit> <file>

Enter fullscreen mode Exit fullscreen mode

Git reset

  • If you accidentally add one or more files into the stashing area, you can run the reset command to solve this problem:
# Exit a file from the staging area
$ git reset <file>
Enter fullscreen mode Exit fullscreen mode
  • Git reset allows you to restore your branch to a specific commit
# Go back to the previous commit and SAVE THE CHANGES 😉
$ git reset --soft HEAD~1

# Go back to the previous commit and DISCARD ALL the changes
$ git reset --hard HEAD~1

# Go back to the second commit in this relative position
$ git reset --hard HEAD~2

# Reset the branch to the remote repo state
# WARNING: This will eliminate your local commits!
$ git reset --hard origin/<branch_name>
Enter fullscreen mode Exit fullscreen mode

I use this git reset when working on a feature or issue in my local branch, I might make several progressive commits, but I prefer not to "clutter" the commit history of the main branch with these intermediate commits. Instead, I aim to deliver a clean and concise PR with a single, well-organized commit.

This approach ensures that only one commit is added to the main branch's history, making it easier for the team or the person responsible for reviewing and merging the PR.

# Here we see only the commits in my local branch
$ git log --oneline --no-merges --branches --not --remotes

0f56980 (HEAD -> preprod) add_FTP_to_GA
1342e47 update_GA

# So, I want only one commit
# First, we reset to the last commit
# ⚠️ use --soft !! 😂
$ git reset --soft HEAD~2

# Then we can do a new sigle commit
$ git commit -m 'Add FTP integration and update GA configuration'

# And now we have only one commit
$ git log --oneline --no-merges --branches --not --remotes

e6bc2e1 (HEAD -> preprod) Add FTP integration and update GA configuration
Enter fullscreen mode Exit fullscreen mode

Git rm

Imagine you added a .env file, committed it, and then realized you forgot to add it to .gitignore... maybe it's not too hard to imagine 🤣.

To fix this, you can use the git rm command. While rm itself is a shell command, git rm is part of Git and provides additional functionality to help us manage files in our repository

# Remove the file from the repository but KEEP it locally
$ git rm --cached .env

# Add it to .gitignore to ensure it's ignored in the future
$ echo ".env" >> .gitignore

# Commit the changes
$ git add .gitignore
$ git commit -m "Remove .env and add it to .gitignore"

Enter fullscreen mode Exit fullscreen mode

Note if you already push le .env file to your remote repo, is always recommended to update yours sensitives keys because one’s the .env file is in the remote repo this information can maybe already by exposed…

Git rebase

The git rebase command is particularly useful when you want to keep your branch up-to-date with the main branch without introducing unnecessary merge commits. For example, if you're working on a feature branch (feature-branch) and the main branch (main) has received updates, you can use git rebase to synchronize your branch with the latest changes. This repositions your commits so they appear as if they were made directly after the latest commits in main, creating a cleaner and more linear history.

This approach makes the commit history easier to read and avoids introducing extra merge commits. It’s especially helpful when collaborating in teams, as it minimizes potential conflicts and simplifies the process of merging your changes back into the main branch.

# In your feature-branch
$ git pull --rebase origin main
# or
$ git fetch origin
$ git rebase origin/main
Enter fullscreen mode Exit fullscreen mode

To ilustrate the situation :

with rebase : A---B---C---D'---E'---F’

without rebase : A---B---C---Merge---D---E---F

Another use case for git rebase is when you want to modify your local branch's commit history before publishing it. It’s important to note that you should avoid making this type of modification if your branch has already been published, as it can generate conflicts by overwriting the existing commit history. You can squash multiple commits into one or change the commit’s messages and more.

# Here, -i is for interactive rebase
# HEAD~4 tells Git that we want to rebase the last 4 commits
$ git rebase -i HEAD~4

# In your text editor, you will see something like this:
pick <hash> Commit message A
pick <hash> Commit message B
pick <hash> Commit message C
pick <hash> Commit message D

# Now, you can modify the commit history:
# - 'reword' allows you to change the commit message of one or more commits.
# - 'squash' tells Git to combine commits into one.

# Example: Changing the message of the second commit and squashing the last two commits into one.
pick <hash> Commit message A
reword <hash> Commit message B  # Change the message of this commit
squash <hash> Commit message C  # Combine this commit with the previous one
squash <hash> Commit message D  # Combine this commit with the previous one

# After saving and closing the editor:
# - If you used 'reword', Git will open an editor to change the commit message.
# - If you used 'squash', Git will prompt you to combine the commit messages.

# This way, you can clean up your commit history, making it more concise and readable before pushing or creating a PR.
Enter fullscreen mode Exit fullscreen mode

I invite you to see more details in the documentation https://git-scm.com/docs/git-rebase

Conclusion

I think that's enough for this post. I have more things to share, but I'll save them for the next one. I'm looking forward to your comments and I hope you've learned something! If you have any recommendations or corrections, please let me know!

Thanks for reading, and see you next time!

Top comments (0)