25 votes

What git commands do you use frequently that you think more people should use?

Some of my favorites are:


git add -p *

This will go through your unstaged changes in chunks and allow you to stage each chunk individually in an interactive shell.


git checkout -p *

Similar to the above, this will go through your unstaged changes and allow you to undo each chunk. I almost never use Ctrl+Z anymore and go straight for this. Want to remove all of those print-debugging statements? Use this command to pluck them out one-by-one.


git commit -a --amend --no-edit && git push --force-with-lease

I alias this one to whoops in my bash profile. It will add all unstaged changes, add them to your last commit and then (safely) force-push the local branch to the tracked remote branch. This is especially useful when working with CI and you need to make constant configuration changes to get it to work. Yes, you could squash those commits afterwards as an alternative. But this is easier.


git rebase -i HEAD~5

(Change 5 to the number of previous commits you want to see)

Interactive rebases are a core part of my git flow when working on feature branches. If a co-worker gives me feedback on a code review that requires a change to a previous commit I'll go back and edit that commit using this command. You can remove individual commits, squash commits, reorder commits, and so much more.

15 comments

  1. undu
    (edited )
    Link
    I consider git unusable without aliases. They are configured using the file ~/.config/git/config. I really prefer aliases to have memorable names for common operations in my git workflow. For...

    I consider git unusable without aliases. They are configured using the file ~/.config/git/config.
    I really prefer aliases to have memorable names for common operations in my git workflow.

    For example for your first command I use:

    [alias]
    # git patch -> stage a file by pieces
      patch = "add --patch"
    

    I also have a series of aliases to print lists about git objects, such as branches, remotes, etc:

    # git contributors -> list contributors of a file
      contributors = "shortlog -s -n"
    
    # git branches -> show branches
      branches = "branch -vv"
    
    # git remotes -> show remote repos
      remotes = "remote -v"
    
    # git tags -> show tags
      tags = "log --oneline --decorate --tags --no-walk"
    
    # git stashes -> show stashes
      stashes = "stash list"
    
    # git changes -> show unstaged changes
      changes = "diff --diff-algorithm=minimal -w"
    

    As a handy way to print the aliases that I have configured in the sistem I have

    # git commands -> show list of the aliases in this file
      commands = "!git config -l|grep alias|cut -c 7-"
    

    All the aliases I use can be found in https://gitlab.com/unduthegun/dotfiles/blob/master/git/.config/git/config#L74

    5 votes
  2. [3]
    Chobbes
    Link
    Can I just say magit?

    Can I just say magit?

    4 votes
    1. [2]
      just_a_salmon
      Link Parent
      For anyone as confused as I was, a “git porcelain” is what the git designers call a UI. It separates the user from the plumbing

      For anyone as confused as I was, a “git porcelain” is what the git designers call a UI. It separates the user from the plumbing

      2 votes
      1. cstby
        Link Parent
        Lol, I never quite got that analogy until reading your comment. I love it. Magit is awesome.

        Lol, I never quite got that analogy until reading your comment. I love it. Magit is awesome.

        1 vote
  3. [3]
    just_a_salmon
    Link
    git rebase -i >>> git merge I have a mildly punny alias for checkout called cz: git cz master

    git rebase -i >>> git merge

    I have a mildly punny alias for checkout called cz: git cz master

    3 votes
  4. [2]
    trunicated
    Link
    git pull --rebase and git merge --squash. Merging your change into mainline should be one commit, not an merge commit with tons of other commits polluting the history. Your change came in at the...

    git pull --rebase and git merge --squash.

    Merging your change into mainline should be one commit, not an merge commit with tons of other commits polluting the history. Your change came in at the time it was merged, the other commits don't matter. And if you need to update before you push, again, you don't need a merge commit. Rebase and fix your problem then push. Stop polluting the history with stupid shit that doesn't matter to anyone else.

    2 votes
    1. teaearlgraycold
      Link Parent
      I don't agree with this. I have inlined git blame information in my editor and it's important for that to be more granular than just a ticket number and a feature summary. A feature will often...

      I don't agree with this. I have inlined git blame information in my editor and it's important for that to be more granular than just a ticket number and a feature summary. A feature will often have multiple steps to it. Maybe a database migration script, some preparatory refactoring, and the actual work.

      And if you need to fix subtle bugs afterwards it's nice to have those in their own commits. That way someone can easily see why those lines specifically were changed.

      4 votes
  5. [4]
    Staross
    Link
    I hate the rebase one, I often want to just squash the last X commits but never remember how to do it exactly and end up messing up my repo half of the time. I wish for a git squash N that just...

    I hate the rebase one, I often want to just squash the last X commits but never remember how to do it exactly and end up messing up my repo half of the time. I wish for a git squash N that just squash the last N commits.

    1 vote
    1. [2]
      MacDolanFarms
      Link Parent
      Another way to squash commits without using rebase: git reset --soft HEAD~4 git commit git reset --soft resets to the specified commit, but leaves the changes staged, so you can just commit then...

      Another way to squash commits without using rebase:

      git reset --soft HEAD~4
      git commit
      

      git reset --soft resets to the specified commit, but leaves the changes staged, so you can just commit then as a single commit.

      5 votes
    2. weystrom
      Link Parent
      Try git rebase -i, if you hate rebase, interactive mode is much easier to manage.

      Try git rebase -i, if you hate rebase, interactive mode is much easier to manage.

      4 votes
  6. heyhup
    Link
    Staging hunks is definitely a powerful feature. However, instead of git add -p I will usually reach for either tig or, more often, just :Gdiffsplit in vim (via vim-fugitive). It's just a more...

    Staging hunks is definitely a powerful feature. However, instead of git add -p I will usually reach for either tig or, more often, just :Gdiffsplit in vim (via vim-fugitive). It's just a more natural way to view and manipulate exactly what I want to commit.

    The git rebase -i functionality looks interesting - that's definitely something I've never used.

    1 vote
  7. Pistos
    Link
    re: git checkout -p: They recently introduced a more sensibly-named alias for this: git restore [-p]

    re: git checkout -p:

    They recently introduced a more sensibly-named alias for this: git restore [-p]

    1 vote