45 classic Git operation scenarios

Respect original copyright: https://www.gewuweb.com/hot/4757.html

45 classic Git operation scenarios

Git should not be unfamiliar to everyone, and proficiency in using git has become a basic skill for programmers, although there are projects such as Sourcetree at work.
In this way, Niu X's client tool makes it very convenient to merge code. But job interviews and some scenarios that need to show personal strength still require us to master enough git commands.

Below we have sorted out 45 classic operation scenarios for daily use of git code, basically covering the needs of work.

What did I just submit?

If you commit a change with git commit -a , and you're not sure exactly what was committed this time. You can display the most recent commit on the current HEAD with the following command:

(main)$ git show  


$ git log -n1 -p  

My commit message is wrong

If your commit message (commit message) is wrong and this commit (commit) has not been pushed (push), you can use the following method to modify the commit message (commit)

$ git commit --amend --only  

This will open your default editor, where you can edit the information. On the other hand, you can do it all at once with one command:

$ git commit --amend --only -m 'xxxxxxx'  

If you have already pushed the commit, you can modify the commit and force push, but this is not recommended.

The username and email address in my commit are incorrect

If this is just a single commit, modify it:

$ git commit --amend --author "New Authorname <authoremail@mydomain.com>"  

If you need to modify all history, refer to the 'git filter-branch' guide page.

I want to remove a file from a commit

Remove a file from a commit by doing the following:

$ git checkout HEAD^ myfile  
$ git add -A  
$ git commit --amend  

This can be very useful when you have an open patch and you committed an unnecessary file to it and you need to force push to update the remote patch.

I want to delete my last commit

If you need to delete the pushed commit
commits), you can use the following method. However, this will irreversibly change your history and also mess up the history of those who have already pulled from the repository. In short, if you're not sure, don't do it.

$ git reset HEAD^ --hard  
$ git push -f [remote] [branch]  

If you haven't pushed to the remote yet, reset Git to the state it was in before your last commit (while saving the staged changes):

(my-branch*)$ git reset --soft HEAD@{1}  

This will only work if you haven't pushed. If you've already pushed, the only safe thing to do is git revert SHAofBadCommit ,
That creates a new commit that undoes all changes from the previous commit; or, if the branch you pushed is rebase-safe
(eg: other developers won't pull from this branch), just use git push -f .

delete any commit

Same caveat: don't do this unless you have to.

$ git rebase --onto SHA1_OF_BAD_COMMIT^ SHA1_OF_BAD_COMMIT  
$ git push -f [remote] [branch]  

Or do an interactive rebase to delete the lines in the commit you want to delete.

I try to push an amended commit (amended commit) to the remote, but I get an error:

To https://github.com/yourusername/repo.git  
! [rejected] mybranch -> mybranch (non-fast-forward)  
error: failed to push some refs to 'https://github.com/tanay1337/webmaker.org.git'  
hint: Updates were rejected because the tip of your current branch is behind  
hint: its remote counterpart. Integrate the remote changes (e.g.  
hint: 'git pull ...') before pushing again.  
hint: See the 'Note about fast-forwards' in 'git push --help' for details.  

Note that rebasing (see below) and amending will replace the old one with a new commit,
So if you've pushed a pre-fix commit to the remote before, you must now force push ( -f ). Note - always
Make sure you specify a branch!

(my-branch)$ git push origin mybranch -f  

In general, avoid pushing hard.
It's better to create and push a new commit than to force a revised commit. The latter would create conflicts in the source history for developers working on that branch or a sub-branch of that branch.

I accidentally did a hard reset and I want to get my content back

If you accidentally do git reset --hard , you can usually get your commits back, because Git keeps a log of everything and keeps it for a few days.

(main)$ git reflog  

You will see a list of your past commits, and a reset commit. Choose the SHA of the commit you want to go back to, and reset it again:

(main)$ git reset --hard SHA1234  

This is done.


I need to add the staged content to the last commit

(my-branch*)$ git commit --amend  

I want to stage part of a new file, not the whole of this file

Generally, if you want to stage part of a file, you can do this:

$ git add --patch filename.x  

-p Shorthand. This will open interactive mode and you will be able to separate commits with the s option; however, if the file is new, this option will not be available,
When adding a new file, do this:

$ git add -N filename.x  

Then, you need to use the e option to manually select the lines you want to add, and running git diff --cached will show which lines are cached and which lines are only saved locally.

I want to add changes in one file to two commits

git add will add the entire file to a commit. git add -p allows interactive selection of the parts you want to commit.

I want to turn the temporary content into unstaged, and temporarily store the unstaged content

In most cases, you should make all content unstaged, and then select the content you want to commit. But assuming that's what you want to do, here you can create a temporary commit to hold your staged content, then stage your unstaged content and stash it. Then reset the last commit to change the originally staged content to unstaged, and finally stash
pop back.

$ git commit -m "WIP"  
$ git add .  
$ git stash  
$ git reset HEAD^  
$ git stash pop --index 0  

Note 1: pop is used here simply because I want to keep it as idempotent as possible. Note 2: If you don't add --index you will mark the staging file as stash.

Unstaged content

I want to move unstaged content to a new branch

$ git checkout -b my-branch  

I want to move unstaged content to another existing branch

$ git stash  
$ git checkout my-branch  
$ git stash pop  

I want to discard local uncommitted changes (uncommitted changes)

If you just want to reset some commits between origin and your local, you can:

# one commit  
(my-branch)$ git reset --hard HEAD^  
# two commits  
(my-branch)$ git reset --hard HEAD^^  
# four commits  
(my-branch)$ git reset --hard HEAD~4  
# or  
(main)$ git checkout -f  

To reset a particular file, you can use the filename as an argument:

$ git reset filename  

I want to discard some unstaged content

If you want to discard some, but not all, of the working copy.

Checkout what you don't need and keep what you need.

$ git checkout -p  
# Answer y to all of the snippets you want to drop  

Another way is to use Stash, Stash everything you want to keep, reset the working copy, and reapply the keep.

$ git stash -p  
# Select all of the snippets you want to save  
$ git reset --hard  
$ git stash pop  

Alternatively, stash the parts you don't need, then stash drop.

$ git stash -p  
# Select all of the snippets you don't want to save  
$ git stash drop  


I pulled from the wrong branch or to the wrong branch

This is another case of using git reflog to find the pointer to HEAD before this error pull.

(main)$ git reflog  
ab7555f HEAD@{0}: pull origin wrong-branch: Fast-forward  
c5bc55a HEAD@{1}: checkout: checkout message goes here  

Reset the branch to your desired commit:

$ git reset --hard c5bc55a  


I want to throw away the local commits so that my branch is consistent with the remote

Make sure you haven't pushed your content to the remote first.

git status will show you how many commits ahead of the origin:

(my-branch)$ git status  
# On branch my-branch  
# Your branch is ahead of 'origin/my-branch' by 2 commits.  
# (use "git push" to publish your local commits)  

One way is:

(main)$ git reset --hard origin/my-branch  

I need to commit to a new branch, but the wrong commit went to main

Create a new branch under main, without switching to the new branch, still under main:

(main)$ git branch my-branch  

Reset the main branch to the previous commit:

(main)$ git reset --hard HEAD^  

HEAD^ is shorthand for HEAD^1 and you can reset it further by specifying which HEAD to set.

Or, if you don't want to use HEAD^ , find the hash of the commit you want to reset to ( git log can do that),
Then reset to this hash. Sync content to remote using git push.

For example, the hash of the commit the main branch wants to reset to is a13b85e :

(main)$ git reset --hard a13b85e  
HEAD is now at a13b85e  

Checkout the newly created branch to continue working:

(main)$ git checkout my-branch  

I want to keep the whole file from another ref-ish

You committed to a branch, saving your work:

(solution)$ git add -A && git commit -m "Adding all changes from this spike into one big commit."  

When you want to put it into a branch (maybe feature , or develop ),
Your concern is to keep the whole file intact, and you want a big commit separated into smaller ones.

Suppose you have:

  • The branch solution , which holds the prototype solution, leads the develop branch.

  • Branch develop , where you apply some content of the prototype scheme.

I can fix this by getting the content into your fork:

(develop)$ git checkout solution -- file1.txt  

This will bring the contents of this file from branch solution to branch develop :

# On branch develop  
# Your branch is up-to-date with 'origin/develop'.  
# Changes to be committed:  
# (use "git reset HEAD <file>..." to unstage)  
# modified: file1.txt  

Then, commit as normal.

Note: Spike solutions are made to analyze or solve the problem. These
solutions are used for estimation and discarded once everyone gets clear
visualization of the problem.

I made several commits to the same branch, and these commits should be distributed in different branches

Suppose you have a main branch, do git log , and you see that you made two commits:

(main)$ git log  
commit e3851e817c451cc36f2e6f3049db528415e3c114  
Author: Alex Lee <alexlee@example.com>  
Date: Tue Jul 22 15:39:27 2014 -0400  
Bug #21 - Added CSRF protection  
commit 5ea51731d150f7ddc4a365437931cd8be3bf3131  
Author: Alex Lee <alexlee@example.com>  
Date: Tue Jul 22 15:39:12 2014 -0400  
Bug #14 - Fixed spacing on title  
commit a13b85e984171c6e2a1729bb061994525f626d14  
Author: Aki Rose <akirose@example.com>  
Date: Tue Jul 21 01:12:48 2014 -0400  
First commit  

Let's flag bugs with commit hashes ( e3851e8 for #21, 5ea5173 for #14).

First, we reset the main branch to the correct commit ( a13b85e ):

(main)$ git reset --hard a13b85e  
HEAD is now at a13b85e  

Now, we create a new branch for bug #21:

(main)$ git checkout -b 21  

Next, we cherry-pick the bug

The commit of 21 is put into the current branch. This means that we will apply this commit, just this one commit, directly on HEAD.

(21)$ git cherry-pick e3851e8  

At this time, conflicts may arise here, see the interactive rebasing chapter Conflicts section to resolve conflicts.

Also, we create a new branch for bug #14, also based on the main branch

(21)$ git checkout main  
(main)$ git checkout -b 14  

Finally, cherry-pick for bug #14:

(14)$ git cherry-pick 5ea5173  

I want to delete the local branch where the upstream branch was deleted

Once you have merged a pull request on github, you can delete the merged branch in your fork. If you are not going to continue working on this branch,
Deleting the local copy of this branch would be cleaner and save you from a mess of working branches and a bunch of stale branches (playing Git in IDEA).

$ git fetch -p  

I accidentally deleted my branch

If you regularly push to the remote, it should be safe in most cases, but sometimes it is possible to delete branches that haven't been pushed to the remote yet. Let's first create a branch and a new file:

(main)$ git checkout -b my-branch  
(my-branch)$ git branch  
(my-branch)$ touch foo.txt  
(my-branch)$ ls  
README.md foo.txt  

Add the file and do a commit

(my-branch)$ git add .  
(my-branch)$ git commit -m 'foo.txt added'  
(my-branch)$ foo.txt added  
1 files changed, 1 insertions(+)  
create mode 100644 foo.txt  
(my-branch)$ git log  
commit 4e3cd85a670ced7cc17a2b5d8d3d809ac88d5012  
Author: siemiatj <siemiatj@example.com>  
Date: Wed Jul 30 00:34:10 2014 +0200  
foo.txt added  
commit 69204cdf0acbab201619d95ad8295928e7f411d5  
Author: Kate Hudson <katehudson@example.com>  
Date: Tue Jul 29 13:14:46 2014 -0400  
Fixes #6: Force pushing after amending commits  

Now we switch back to the main (main) branch and 'accidentally' delete the my-branch branch

(my-branch)$ git checkout main  
Switched to branch 'main'  
Your branch is up-to-date with 'origin/main'.  
(main)$ git branch -D my-branch  
Deleted branch my-branch (was 4e3cd85).  
(main)$ echo oh noes, deleted my branch!  
oh noes, deleted my branch!  

At this point you should be reminded of reflog , an updated version of the log that stores the history of all actions in the repository (repo).

(main)$ git reflog  
69204cd HEAD@{0}: checkout: moving from my-branch to main  
4e3cd85 HEAD@{1}: commit: foo.txt added  
69204cd HEAD@{2}: checkout: moving from main to my-branch  

As you can see, we have a commit hash from the deleted branch, let's see if we can restore the deleted branch.

(main)$ git checkout -b my-branch-help  
Switched to a new branch 'my-branch-help'  
(my-branch-help)$ git reset --hard 4e3cd85  
HEAD is now at 4e3cd85 foo.txt added  
(my-branch-help)$ ls  
README.md foo.txt  

Look! We got the deleted files back. Git's reflog is also useful when rebasing goes wrong.

I want to delete a branch

Delete a remote branch:

(main)$ git push origin --delete my-branch  

you can also:

(main)$ git push origin :my-branch  

Delete a local branch:

(main)$ git branch -D my-branch  

I want to checkout a branch from a remote branch that someone else is working on

First, fetch all branches from the remote:

(main)$ git fetch --all  

Suppose you want to checkout from the remote daves branch to the local daves branch

(main)$ git checkout --track origin/daves  
Branch daves set up to track remote branch daves from origin.  
Switched to a new branch 'daves'  

( --track is shorthand for git checkout -b [branch] [remotename]/[branch] )

This gives you a local copy of the daves branch, and any pushed updates will be visible to the remote.

Rebasing and Merging

I want to undo the rebase/merge

You can merge or rebase the wrong branch, or fail to complete an ongoing rebase/merge. Git
The original HEAD is stored in a variable called ORIG_HEAD during dangerous operations, so it is easy to restore the branch to its pre-rebase/merge state.

(my-branch)$ git reset --hard ORIG_HEAD  

I've rebase, but I don't want to force push

Unfortunately, if you want to reflect these changes on the remote branch, you have to force push. because you Fast forward
forward) commits, changing the Git history, remote branches will not accept changes unless force push. This is how many people use the merge workflow,
Rather than one of the main reasons for rebasing workflows, developer force pushes can get big teams into trouble. Pay attention when using, a safe use of rebase
The way to do this is, instead of reflecting your changes to the remote branch, do the following:

(main)$ git checkout my-branch  
(my-branch)$ git rebase -i main  
(my-branch)$ git checkout main  
(main)$ git merge --ff-only my-branch  

I need to combine several commits

Suppose your working branch will do a pull-request to main . In general you don't care about commit timestamps, you just want to combine all
Commit to a single one, then reset and recommit. Make sure the main branch is up to date and your changes are committed, then:

(my-branch)$ git reset --soft main  
(my-branch)$ git commit -am "New awesome feature"  

If you want more control, and want to preserve timestamps, you need to do an interactive rebase:

(my-branch)$ git rebase -i main  

If there is no other branch relative to it, you will have to rebase relative to your own HEAD. For example: you want to combine the last two commits, you would rebase relative to HEAD~2, combine the last 3 commits, relative to HEAD~3, etc.

(main)$ git rebase -i HEAD~2  

After you execute the interactive rebase command, you will see something like the following in your editor:

pick a9c8a1d Some refactoring  
pick 01b2fd8 New awesome feature  
pick b729ad5 fixup  
pick e3851e8 another fix  
# Rebase 8074d12..b729ad5 onto 8074d12  
# Commands:  
# p, pick = use commit  
# r, reword = use commit, but edit the commit message  
# e, edit = use commit, but stop for amending  
# s, squash = use commit, but meld into previous commit  
# f, fixup = like "squash", but discard this commit's log message  
# x, exec = run command (the rest of the line) using shell  
# These lines can be re-ordered; they are executed from top to bottom.  
# If you remove a line here THAT COMMIT WILL BE LOST.  
# However, if you remove everything, the rebase will be aborted.  
# Note that empty commits are commented out  

All lines starting with # are comments and do not affect rebase.

You can then replace pick with any of the commands in the command list above, and you can also remove a commit by removing the corresponding line.

For example, if you want to keep the oldest (first) commit alone, combine all the rest into the second one,
You should then edit the word before each commit after the second commit to f :

pick a9c8a1d Some refactoring  
pick 01b2fd8 New awesome feature  
f b729ad5 fixup  
f e3851e8 another fix  

If you want to combine these commits and rename this commit, you should add an r next to the second commit
, or simply replace f with s :

pick a9c8a1d Some refactoring  
pick 01b2fd8 New awesome feature  
s b729ad5 fixup  
s e3851e8 another fix  

You can rename the commit in the text prompt that pops up next.

Newer, awesomer features  
# Please enter the commit message for your changes. Lines starting  
# with '#' will be ignored, and an empty message aborts the commit.  
# rebase in progress; onto 8074d12  
# You are currently editing a commit while rebasing branch 'main' on '8074d12'.  
# Changes to be committed:  
#modified: README.md  

If successful, you should see something similar to the following:

(main)$ Successfully rebased and updated refs/heads/main.  

Safe merging strategy

--no-commit Perform a merge without auto-commit, giving the user the opportunity to review and make changes before committing. no-ff will be a feature branch
The existence of branch) has left evidence to keep the project history consistent (for more Git information, see How to complete Git version rollback in IDEA?).

(main)$ git merge --no-ff --no-commit my-branch  

I need to merge a branch into a commit

(main)$ git merge --squash my-branch  

I just want to combine the unpushed commits

Sometimes you have several work-in-progress commits before pushing data upstream. At this point, you don't want to include pushed combinations, because others may already have commits referencing them.

(main)$ git rebase -i @{u}  

This will generate an interactive rebase, which will only list commits that were not pushed,
It is safe to reorder/fix/squash this list.

Check if all commits on the branch have been merged

To check if all commits on one branch have been merged into other branches, you should do a diff between the heads (or any commits) of those branches:

(main)$ git log --graph --left-right --cherry-pick --oneline HEAD...feature/120-on-scroll  

This will tell you a list of all commits that are in one branch but not the other, and commits that are not shared between branches. Another approach could be:

(main)$ git log main ^feature/120-on-scroll --no-merges  

Possible problems with interactive rebase

This rebase edit screen shows 'noop'

If you see this:


This means that the branch you rebase is on the same commit as the current branch, or ahead of the current branch. You can try:

  • Check to make sure the main (main) branch is OK

  • rebase HEAD~2 or earlier

conflict situation

If you cannot successfully complete the rebase, you may have to resolve conflicts.

First execute git status to find out which files are in conflict:

(my-branch)$ git status  
On branch my-branch  
Changes not staged for commit:  
(use "git add <file>..." to update what will be committed)  
(use "git checkout -- <file>..." to discard changes in working directory)  
modified: README.md  

In this example, README.md has a conflict. Open the file and find something similar to the following:

 <<<<<<< HEAD  
some code  
some code  
>>>>>>> new-commit  

You need to address the difference between the newly committed code (in the example, from the middle == line to the new-commit ) and HEAD.

Sometimes these merges are very complex and you should use a visual diff editor:

(main*)$ git mergetool -t opendiff  

After you've resolved all conflicts and tests, git add the changed files, then use git rebase --continue
Continue to rebase.

(my-branch)$ git add README.md  
(my-branch)$ git rebase --continue  

If after resolving all conflicts, you get the same result as before committing, you can execute git rebase --skip .

Anytime you want to end the entire rebase process and go back to the state of the branch before the rebase, you can do:

(my-branch)$ git rebase --abort  


Staging all changes

Staging all changes in your working directory

$ git stash  

You can use -u to exclude some files

$ git stash -u  

Temporarily save the specified file

Suppose you only want to stage a certain file

$ git stash push working-directory-path/filename.ext  

Suppose you want to stage multiple files

$ git stash push working-directory-path/filename1.ext working-directory-path/filename2.ext  

Log messages while staging

This way you can see it when list ing

$ git stash save <message>  


$ git stash push -m <message>  

use a specified staging

First you can check your stash records

$ git stash list  

Then you can apply a certain stash

$ git stash apply "stash@{n}"  

Here, 'n' is the position of the stash on the stack, the top stash will be 0

Other than that, time stamping can be used (if you can remember it).

$ git stash apply "stash@{2.hours.ago}"  

Keep unstaged content when staging

You need to manually create a stash commit and then use git stash store .

$ git stash create  
$ git stash store -m "commit-message" CREATED_SHA1  

Miscellaneous Objects

clone all submodules

$ git clone --recursive git://github.com/foo/bar.git  

If already cloned:

$ git submodule update --init --recursive  

delete tag

$ git tag -d <tag_name>  
$ git push <remote> :refs/tags/<tag_name>

restore deleted tags

If you want to restore a deleted tag, you can follow the steps below: First, you need to find the unreachable tag:

$ git fsck --unreachable | grep tag  

Write down the hash of this tag (tag), and then use Git's update-ref

$ git update-ref refs/tags/<tag_name> <hash>  

At this point your tags should have been restored.

Patch removed

If someone sends you a pull request on GitHub, but then he deletes his own original fork, you won't be able to clone their commit or use
git am . In this case, it's better to manually review their commits, copy them to a new local branch, and do the commits.

Tracking Files

I just want to change the case of a file name without modifying the content

(main)$ git mv --force myfile MyFile  

I want to delete a file from Git, but keep the file

(main)$ git rm --cached log.txt  


I want to add aliases to some Git commands

Under OS X and Linux, your Git configuration files are stored in ~/.gitconfig . I am in [alias]
Some shortcut aliases (and some I easily misspelled) have been added to the section, as follows:

a = add  
amend = commit --amend  
c = commit  
ca = commit --amend  
ci = commit -a  
co = checkout  
d = diff  
dc = diff --changed  
ds = diff --staged  
f = fetch  
loll = log --graph --decorate --pretty=oneline --abbrev-commit  
m = merge  
one = log --pretty=oneline  
outstanding = rebase -i @{u}  
s = status  
unpushed = log @{u}  
wc = whatchanged  
wip = rebase -i @{u}  
zap = fetch -p  

I want to cache username and password for a repository

You may have a repository that requires authorization, then you can cache the username and password instead of typing it every time you push/pull, the Credential helper can help you.

$ git config --global credential.helper cache  
# Set git to use the credential memory cache  

$ git config --global credential.helper 'cache --timeout=3600'  
# Set the cache to timeout after 1 hour (setting is in seconds)  

I don't know what I'm doing wrong

You screwed up: you reset something, or you merged the wrong branch, or you can't find your own commit after a push. sometimes,
You've been doing great, but you want to go back to a certain state before.

This is the purpose of git reflog, reflog records any changes to the tip of a branch,
Even that tip is not referenced by any branch or tag. Basically, every time HEAD changes, a new record is added to the reflog
. Unfortunately, this only works on local branches, and it only tracks actions (e.g. will not track any changes to an undocumented file).

(main)$ git reflog  
0a2e358 HEAD@{0}: reset: moving to HEAD~2  
0254ea7 HEAD@{1}: checkout: moving from 2.2 to main  
c10f740 HEAD@{2}: checkout: moving from main to 2.2  

The reflog above shows a checkout from the main branch to the 2.2 branch, and back again. There, there is also a hard reset (hard
reset) to an older commit. The most recent action appears at the top with a HEAD@{0} sign.

If it turns out that you accidentally moved back a commit, the reflog will contain the commit you pointed to on main before you accidentally moved back (0254ea7).

$ git reset --hard 0254ea7  

Then use git reset to change main back to the previous commit, which provides a safety net in case the history is accidentally changed.

For more content reference: https://www.gewuweb.com/sitemap.html

Posted by RalphDesign on Sat, 07 May 2022 08:16:20 +0300