DEV Community

Cover image for 3 Terminal Commands to Increase Your Productivity
Pankaj Gupta
Pankaj Gupta

Posted on

3 Terminal Commands to Increase Your Productivity

Here are a few important shortcuts that help me be more productive throughout the day at work:

  • Creating aliases for commands.
  • Using pbcopy.
  • Using reverse search in the terminal.
  • Bonus tricks and tips.

Alias for Commands

Alias can be one of the most powerful tools in our hands, it provides us with the power to write our own shortcuts. Let’s see with an example what I mean.



alias dev="cd ~/Project/development"


Enter fullscreen mode Exit fullscreen mode

Whenever I type dev and hit enter it’ll run this command. This becomes very useful when navigating to different folders. We can run almost all the commands in the alias. Here is the list of some of my most-used commands:



alias ..="cd .."
alias gs="git status"
alias gp="git pull"
alias gb="git branch"
alias ga="git add ."


Enter fullscreen mode Exit fullscreen mode

So, using these aliases, I save a lot of time during the day, to up a directory I type, instead of cd… I think the rest of them are self-explanatory. We can also use arguments with $1, $2, etc. for more extendability, like in this example:



alias gc="git commit -m $1"


Enter fullscreen mode Exit fullscreen mode

Now, all I have to type is gc “Commit message” and it’ll commit my changes with the provided message. All you have to do is find your most-used commands and try to make them shorter using an alias to make yourself more productive.

Now that we know what the aliases can do, let us see how we can set them. There are two ways in which we can achieve this, the first is temporary and can be set by running the command:



alias dev="cd ~/Project/development"


Enter fullscreen mode Exit fullscreen mode

This will work until the session is closed. The other way is to set these aliases permanently. For that, we need to set it up in our shell, I use Zsh, so I’ll be updating my ~/.zshrc file.

If you are using Bash, use the ~/.bashrc file. Add the commands to the file and your file should look like this:

.zshrc file

After making changes to this file, you need to run the command:



source ~/.zshrc


Enter fullscreen mode Exit fullscreen mode

Then, all your aliases will be available for your use.


pbcopy

This command is available on Mac and if you want to use it on Linux distributions, you can follow this guide.

pbcopy is copy on steroids. You can use this command to copy the contents of a file to the clipboard. Let me give you an example. Suppose you have to copy your SSH identity to the clipboard, you can do it with this command:



pbcopy < ~/.ssh/id_rsa.pub


Enter fullscreen mode Exit fullscreen mode

You can save your other passwords in different files and make use of this while logging in.

Suppose you are using and accessing a remote server, and you have to provide the password, instead of opening the file, you can just pbcopy it to your clipboard and without all the hassle of opening and closing files, you’ll have the passwords.

It becomes more useful when it is piped with other commands like grep. It’ll copy the grepped results to the clipboard. Let’s see with an example:



grep "<keyword>" | pbcopy


Enter fullscreen mode Exit fullscreen mode

I use this command when I am debugging the log files, and I provide a keyword to be searched for, like a timestamp, and all the lines are copied onto my clipboard.

I can paste it in a file to see the required logs instead of the whole file. It can be even more useful if you use the tee command as a pipe to grep, it’ll write the results to a file.

It has the following syntax:



grep "<keyword>" | tee myfile.txt


Enter fullscreen mode Exit fullscreen mode

Using Reverse Search

Reverse search is one of the coolest things available on the Unix system.

Suppose you forget the full command and you only remember some parts, what you can do is you can go to the reverse search and type the words that you remember. Let’s see it with an example.

I have to restart my server running in the staging environment, I only remember the staging keyword and forgot the rest of the command. So, I type ctrl + rto go into reverse-search mode and type:



(reverse-i-search)`stag': cd /home/ubuntu/server; pm2 stop app.js && export NODE_ENV="staging" && pm2 start app.js && pm2 logs
```

It’ll remember the commands previously entered and finds the right match that you are looking for.

---

## Bonus Tricks and Tips

### cal
It prints the current month on the terminal. It has many different options available, which can be checked using man cal.


![Calendar View](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ronihzsjagme3dp5fifp.png)

### Encrypting a file using vim

You can encrypt a file using vim, just type :X. It’ll ask you to set a password which will look like this:


![Encrypting a file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4uunprvj2jm2do8azxe1.png)

When you access this file again, it’ll ask you for the password.


![Opening an encrypted file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ke8oweb76p36djzxf0kz.png)

---

## Conclusion

Please do mention your most used commands and add to the list.
Enter fullscreen mode Exit fullscreen mode

Top comments (46)

Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️
alias gc="git commit -m $1"
Enter fullscreen mode Exit fullscreen mode

I hate this one with a passion. People who have aliases like this are almost always the same people who only ever write one-liner commit messages, no matter how simple or complex the actual commit is.

But what they lose by writing one-liners, they often make up with line length, often going way over the best practice character limit.

I really wish committing with -m was just locked for anyone who hasn't been using git for at least 5 years and knows what they're doing.

Collapse
 
viiik profile image
Eduard

Why would you need multi line commit messages? A commit message should be a name and that's it, leave the details for the PR that will eventually squash all commits into a final frozen commit (which will include all the details)

Collapse
 
cappe987 profile image
Casper

When browsing the git logs I don't want to have to find the merge commit to get details about what one commit changed. A commit should, when necessary, explain the changes and maybe the reasoning for it. It's painful when I want to find out why a change was made but the commit doesn't explain anything.

Squashing all commits into one is not good practice in my opinion. If you are going to do squashing, do it in a controlled manner with rebase. Taking 10 commits and squashing into 1 loses a ton of information if the commits were well written.

Collapse
 
goodevilgenius profile image
Dan Jones

PRs are tied to GitHub. Commit messages are agnostic to which git forge you're using. When I want to see why a change was made, I git blame the file, and look at the commit message for that change.

Squashing commits should generally be avoided because you lose a lot of information from individual commits.

Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️

I think you're a bit too fixated on your own non-standard git workflow there.

I also sometimes use a sort of throw-away git history where some commits are just "fix", that I later intend to clean up with a rebase. If you want to make that your main workflow for every branch, then sure, you can be a lot less thorough with your individual commit messages.

But the "intended", and afaik most common way of using git, is to keep commits atomic, and have their messages describe the change that was made. If the reason for a change isn't obvious from just looking at the code and maybe some extra context from previous commits (or from a later merge commit), then that should be explained in the commit message.

Putting too much information in a single commit really just makes it hard to reason about the individual parts that make up a larger change, like introducing a new feature. If all you see in your git history is "add feature X", then that's hardly better than a normal change log, and you lose all the important step-by-step information of how feature X was actually added, what preparations were necessary, etc. as well as the ability to undo individual changes if necessary.

Thread Thread
 
viiik profile image
Eduard

Yeah perhaps my workflow is uncommon. My commits are still atomic however, just at the master branch, not my working branch. And usually extra context lives in the task definition that originated the changes, which is usually linked in the PR which ultimately forma part of the master commit description.

Thread Thread
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️

The problem with that approach is that it doesn't work for everyone, because both github PRs and obviously anything linked from them as well exist outside of the repository. So anyone aiming for having as much context as possible contained in the repository itself will have to avoid those.

As for atomic, please note that entire features aren't usually atomic. The point of atomic commits is that they make changes that ideally don't break the project, but also cannot be split into smaller non-breaking changes. The way I most commonly see git used, is that commits generally represent atomic changes, while higher-level concepts like "features" tend to be represented by merges.

Collapse
 
greenteaisgreat profile image
Nathan G Bornstein

I agree that leaving a detailed commit message is really important. It saves so much time for both the creator and anyone working in that codebase in the future. But most commit messages can be within the 50-72 character count without the need for multi-line messages

If you're adhering to best practices, atomic commits should also be another tenet to follow. Small, succinct changes need to be committed as soon as they're completed, rather than big changes that would necessitate multi-line messages

Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️

Yes, it is correct that the majority of commits can do just fine with a single line of description. My problem is with how using -m (or an alias) often makes people write one-liners even if a longer commit message would be preferable, because now that would be a deviation from their usual workflow.

Even worse: Noticing while writing the message that it is a bit more complicated, now the user has to delete what they already typed, commit without -m and write it all again in the editor (or at best copy-paste it), which is more resistance that more often than not makes people just cut their messages shorter than they should be.

Collapse
 
thenickest profile image
TheNickest

A good engineer should understand best practices in 5 minutes. Then needs maybe 5 more days to make them a habit. If anyone needs 5 years for this, something else goes wrong.

Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️

The problem is that complicated commits that need multi-line messages are generally a rarity, so "building habits" around those cases is difficult.

Using the editor to write commit messages means there is no barrier to decide halfway through the commit line that you need to add some additional context, and just write it down.

Being used to using -m, on the other hand, puts a lot of resistance in the way of doing this, so in the worst case, people simply skip the extra context or attempt to shove it all into an incomprehensible commit line, and at best requires some discipline to do things differently.

Collapse
 
qainsights profile image
NaveenKumar Namachivayam ⚡

IMO there is nothing wrong using commit message in one line. But when you submit a PR, I'd expect the purpose of the PR, what gets a fix and what not. :)

Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️

Yea, most of the time a one-liner is enough and you shouldn't write a novel in a commit message; that's why an alias like gc is very useful in principle.

I'm specifically worried that it creates a habit, and in the rare cases where you do need more information, that habit tempts people to just skip the important stuff because writing a commit message in the editor now falls outside of their routine.

Collapse
 
asenar profile image
Asenar

About this, I really like this article about how to write a really useful commit message : chris.beams.io/posts/git-commit/

Collapse
 
pankajgupta221b profile image
Pankaj Gupta

I'm sorry but I've to ask, if you have pull request changes, and have to make multiple commits, what kind of commit message do you give in that case?

Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️

I don't think I fully understand your question. Can you give an example of what you mean?

Thread Thread
 
pankajgupta221b profile image
Pankaj Gupta

Suppose you submit a Pull Request, and the reviewer suggested some changes, which you've to make, for that there are two options, you can edit the commit or you can add a new commit, if you go with the latter approach, what kind of commit message do you prefer, the whole explanation for the feature for which you are working or just the minor changes you've made like, "added title".

Thread Thread
 
cappe987 profile image
Casper

Why would you explain the whole feature again? That's clearly wrong, you already have a commit that does that.

But please don't keep it as short as "added title". That looks horrible when browsing the logs, just a bunch of "fixed bug", "added text", etc. Provide more details like "Added title to help text for [feature name]" or "Fix X bug in [feature name]" (with details on what X was in the commit body, it's annoying to see a bugfix that doesn't explain why it was needed because the change doesn't always make sense to someone else).

Thread Thread
 
mickmister profile image
Michael Kochell

That looks horrible when browsing the logs

@cappe987 When you say "logs", do you mean the overall commit logs of the repository, or the commit logs of a given PR? The comment thread here has implied that the commits of a PR will be squashed into one commit. Maybe you aren't making that same assumption.

In the case of squashing the commits per-PR, each commit on the main branch will be tidy, and have the whole context of that PR. For individual commits in a PR, I'm not sure if we need to include the feature name in the commit message, especially if the PR is scoped to one feature.

Imo, every commit should go through a PR, and should not be committed to the main branch. The only time I bypass a PR in my own projects is if I want to make a small change to the README. And for that, I will be descriptive with my commit message on what I'm changing in the README.

Thread Thread
 
cappe987 profile image
Casper

I mean the git log.

I was talking under the assumption that no squashing is done (or controlled squashing with rebase). I mentioned in another comment here that sqashing a full PR is not good practice in my opinion. You lose a lot of information if the commits are well written. Of course it depends on how the PR looks. If it's just one commit with a bunch of small adjustments afterwards the feel free to squash. If the original PR is made up of, say, 5 carefully written commits that together add a feature then please don't squash.

Yes, one squashed commit looks tidy. But you know what's better? 5 commits that explain the different steps in adding that feature, instead of one giant commit.

Having detailed git logs is incredibly useful. I don't want to locate the original PR to get the full context.

I'm not disputing using PRs, I'm only against indiscriminate squashing. And if a commit is gonna be in the final git logs then it should be well written.

Thread Thread
 
mickmister profile image
Michael Kochell • Edited

Having the commits be one per-PR allows us to compare branches, and see the most concise summary of the differences of the branches. "This branch has 3 PRs/features/fixes merged on top of the other", whereas if a given PR is merged and spread out to multiple commits, it's unclear exactly which PRs were merged on each one, and which PR that commits are related to. This is important for me to be able to pull individual PRs into a separate branch to release a patch release for something.

Having the commits squashed also makes it easier to revert the entire PR by git reverting the squashed commit. There are tradeoffs to this, as one could favor the benefit of being able to revert only one of the commits related to that PR. Though I prefer the squashed commit scenario, since you can view each PR as its own unit of work for development and QA, that can be reverted if needed.

Having detailed git logs is incredibly useful. I don't want to locate the original PR to get the full context.

If you structure the squash commit message to summarize the PRs commits, you can still achieve this by viewing this message in the git log output. The commit history of the PR is automatically populated in the squash commit message box while you are merging the PR, so you can edit from there if you want or keep it just the original commit messages.

I've gotten accustomed to a workflow that works with squashing commits, so I'm biased, but I would personally never go back to not squashing commits because of the benefits I've described here.

Thread Thread
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️

...everything you just described is exactly what merge commits are for though; they preserve the individual commits of both branches but group together groups of atomic changes that represent a higher level change.

Not to say either approach is inherently correct, but you make it sound a bit like your approach is the only one that gets you those benefits, when you can easily get those in a different way, just, well, a bit different.

Thread Thread
 
mickmister profile image
Michael Kochell

The behavior of git log and ease of reverting a PR is not the same in the two scenarios though right? I'm legitimately not sure about the specifics of merge commits in this regard. I prefer git log to show one commit per PR on the main branch.

Thread Thread
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️ • Edited

So I got curious and decided to just experiment a bit. Created a simple dummy repository that looks like this:

*   c258407 (HEAD -> main) Implement Feature A
|\  
| * 8de3de7 (feature_a) Do thing 3
| * 0e25efc Do thing 2
| * 63cabce Do thing 1
|/  
* 1ff8ad2 Initial
Enter fullscreen mode Exit fullscreen mode

with a single "feature" branch that has three individual commits. The second one has some dummy "extra information" that I would want to preserve in a real-world scenario:

commit 0e25efcf2d94ae556c871f8330c0b7c55116ff41
Author: DarkWiiPlayer <darkwiiplayer@hotmail.com>
Date:   Fri Jan 5 08:48:45 2024 +0100

    Do thing 2

    Thing 1 did a thing that broke stuff in subtle ways.
    To migitage this, thing 2 foos the bars every day.
    If this breaks again in the future, apply extra grease.
Enter fullscreen mode Exit fullscreen mode

After digging through the git log manpage for a bit, I found --merges, but that has the disadvantage of only displaying merge commits, so any potential hotfixes on main could get lost (maybe this is what you want, but I wasn't entirely satisfied). But just under that there's also the --first-parent flag, which will only follow the first parent on merge requests, which in practice is what you merged into, aka. the main branch. This gives me the following log:

λ git log --first-parent 
commit c258407f6af5aee657744910b8ba68c1cfa2121e (HEAD -> main)
Merge: 1ff8ad2 8de3de7
Author: DarkWiiPlayer <darkwiiplayer@hotmail.com>
Date:   Fri Jan 5 08:54:51 2024 +0100

    Implement Feature A

    As requested by accounting, this should make the process more ergonomic.

commit 1ff8ad22557a9429aff4788c0efdeef9171a1211
Author: DarkWiiPlayer <darkwiiplayer@hotmail.com>
Date:   Fri Jan 5 08:47:54 2024 +0100

    Initial
Enter fullscreen mode Exit fullscreen mode

Meanwhile the feature branch can be safely removed now, as the commits live within the main branch and can easily be displayed:

λ git log "main~1..main^2"
commit 8de3de7b445102c9d5bcfb7f5b18a509065a37c9 (feature_a)
Author: DarkWiiPlayer <darkwiiplayer@hotmail.com>
Date:   Fri Jan 5 08:48:57 2024 +0100

    Do thing 3

commit 0e25efcf2d94ae556c871f8330c0b7c55116ff41
Author: DarkWiiPlayer <darkwiiplayer@hotmail.com>
Date:   Fri Jan 5 08:48:45 2024 +0100

    Do thing 2

    Thing 1 did a thing that broke stuff in subtle ways.
    To migitage this, thing 2 foos the bars every day.
    If this breaks again in the future, apply extra grease.

commit 63cabcea5ff39852b8d5385e78ed9c1a15ca6f5f
Author: DarkWiiPlayer <darkwiiplayer@hotmail.com>
Date:   Fri Jan 5 08:48:29 2024 +0100

    Do thing 1
Enter fullscreen mode Exit fullscreen mode

So overall, I would say that yea, a merge-commit based workflow can offer the same information as one based on commit squashing, and it's not even all that difficult.

And of course, git aliases can make things even easier:

git config alias.main "log --first-parent"
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
mickmister profile image
Michael Kochell

Thanks for digging into this so deeply. The --merges and --first-parent flags look very useful here. Really insightful conclusion overall.

Collapse
 
proteusiq profile image
Prayson Wilfred Daniel • Edited

🫣 instead of aliasing directories, use zoxide. After the first cd /this/is/batman then you can just do z batman.

🎉😎 See CLI tools you cant live without

Collapse
 
asenar profile image
Asenar

bash aliases are great, but for git sub commands I personally prefer (and recommend) to use [alias] section in .gitconfig.

Collapse
 
goodevilgenius profile image
Dan Jones

For a good Linux alternative to pbcopy and pbpaste, try out xclip.

grep text file.txt | xclip -i # copies into primary selection

grep text file.txt | xclip -i -sel clip # copies into clipboard

xclip -o # prints primary selection
xclip -o -sel clip # prints clipboard, like pbpaste

# highlight a selection of text, you don't need to Ctrl-c, just highlight
xclip -o > out.txt # pastes that selection into a file
Enter fullscreen mode Exit fullscreen mode

And if you're using Termux on Android, termux-clipboard-get and termux-clipboard-set give you access to the Android clipboard.

Collapse
 
walfal profile image
Walfal

I have these ones in my zshrc, near others for Linux

alias G=’| grep --color=auto
gitcommit(){
# All element except the last one
git add "${@: 1:-1}"
# Last element
git commit -m "${@: -1:1}"
}
alias ggc=gitcommit

Adding all alias in the plugin git in zsh :)

Collapse
 
moopet profile image
Ben Sinclair

Some problems here:

aliases

This doesn't do what you think it does:

alias gc="git commit -m $1"
Enter fullscreen mode Exit fullscreen mode

The $1 isn't expanded to anything in your alias. It works because your message goes at the end of the line. You can see this if you try a little test:

$ alias foo="echo BEGIN $2 $1 END"

$ foo one two three
BEGIN END one two three
Enter fullscreen mode Exit fullscreen mode

If you want to use substitution then you should be using a function or a script, not an alias.

pbcopy

You go on to say

This command is available on Mac and if you want to use it on Linux distributions, you can follow this guide.

But you don't provide any guides for Linux. If you want similar functionality to pbcopy, you're probably looking for xsel or xclip but ymmv.

reverse search

This isn't a command at all! It's a feature of the input library. I think from memory this is readline most of the time. It gives you a bunch of nice features like the reverse search you mentioned, and it will work that way in any application which uses that library. This means that you can be using something like the mysql client, or a programming language REPL and there's a reasonable chance you have the same super powers there too.

Collapse
 
orenc profile image
Chanan Oren

Instead of the cd alias, on ZSH there is a named directory feature:

hash -d shortname=~/some/long/path  # can add this line to your ~/.zshrc
# then you can:
cd ~shortname
Enter fullscreen mode Exit fullscreen mode
Collapse
 
mhubbardvect profile image
mhubbard-vect

With ZSH you can put all of your custom aliases in a custom file. Default location is ~/.oh-my-zsh/custom.

I use ~/.oh-my-zsh/custom/zsh-aliases

I preface my aliases with my initials and a - , mw- in my case.

Then I can type mw- [tab] to see all of my aliases.

I also created an alias that opens the custom alias file.

As mentioned above ZSH includes a lot of aliases and you can use the "aliases" plug in to display all installed ZSH aliases

This is what my ZSH plugins looks like:
plugins=(
git
zsh-completions
zsh-autosuggestions
zsh-syntax-highlighting
history-substring-search
colored-man-pages
aliases
zsh-docker-aliases
)

github.com/ohmyzsh/ohmyzsh/tree/ma...

Collapse
 
orenc profile image
Chanan Oren

You are aware that OMZ is not required? Nothing OMZ does can't be done without it, it's all ZSH scripts. Though, yes you can source any file you want in to your .zshrc (or any shell script).

Collapse
 
manvendrask profile image
Manvendra Singh

Use OhMyZsh

Collapse
 
hellosurya1010 profile image
Surya K

Wow 😲 these alias commands are awesome 🔥🔥🔥

Collapse
 
pankajgupta221b profile image
Pankaj Gupta

Thank you so much!