Git should not be unfamiliar to everyone, proficient use of git has become a basic skill for programmers, although there are awesome client tools such as Sourcetree in the work, which makes merging codes very convenient. But for job interviews and some scenes that need to show personal strength, we still need to master enough git commands.
Below we have sorted out 45 classic operation scenarios for daily use of git to combine codes, which basically cover the needs of work.
What did I just submit?
If you git commit -a
submit a change (changes) with , and you are not sure what content was submitted this time. You can use the following command to display HEAD
the latest commit (commit):
(main)$ git show
or
$ git log -n1 -p
My commit message is wrong
If your commit message is written wrong and this commit has not been pushed yet, you can modify the commit message by the following method:
$ git commit --amend --only
This will open your default editor, where you can edit the message. Alternatively, you can do it all at once with a single command:
$ git commit --amend --only -m 'xxxxxxx'
If you have already pushed this commit, you can modify this commit and force push, but this is not recommended.
The user name and email address in my commit (commit) are wrong
If this is just a single commit, modify it:
$ git commit --amend --author "New Authorname <[email protected]>"
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:
$ git checkout HEAD^ myfile
$ git add -A
$ git commit --amend
This will be very useful when you have an open patch (open patch), you submit an unnecessary file to it, and you need to force push (force push) to update the remote patch.
I want to delete my last commit (commit)
If you need to delete pushed commits, you can use the following method. However, this will irreversibly change your history and mess up the histories 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, just reset Git to where it was before your last commit (while saving the staged changes):
(my-branch*)$ git reset --soft HEAD@{1}
This only works if you haven't pushed before. If you've already pushed, the only safe thing to do is git revert SHAofBadCommit
to create a new commit that undoes all the changes from the previous commit; or, if you push This branch of is rebase-safe (for example: other developers will not pull from this branch), just use it git push -f
.
Delete any commit
Same warning: don't do this unless you absolutely have to.
$ git rebase --onto SHA1_OF_BAD_COMMIT^ SHA1_OF_BAD_COMMIT
$ git push -f [remote] [branch]
Or do an interactive rebase and delete the lines corresponding to the commits you want to delete.
I tried to push an amended commit (amended commit) to the remote, but got 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 commit with a new one , so if you have pushed a pre-amended commit to the remote repository 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 . It is better to create and push a new commit than to push a revised commit. The latter would create conflicts in the source history for developers working on that branch or a subbranch of that branch.
I accidentally did a hard reset and I want to get my content back
If you do it by accident git reset --hard
, you can usually get your commit back, because Git keeps a log of everything, and keeps it for a few days.
(main)$ git reflog
You'll 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 again:
(main)$ git reset --hard SHA1234
This is done.
Staging
I need to add the staging content to the last commit
(my-branch*)$ git commit --amend
I want to stage part of a new file, not the whole file
In general, if you want to stage a portion of a file, you do this:
$ git add --patch filename.x
-p
Shorthand. This will open interactive mode and you will be able s
to separate commits with options; however, if the file is new, there will be no such option. When adding a new file, do this:
$ git add -N filename.x
Then, you need to use e
the option to manually select the lines to be added, and the execution git diff --cached
will show which lines are staged 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 change the temporarily stored content to unscheduled, and temporarily store the unscheduled 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 save your staged content, then stage your unstaged content and stash. Then reset the last commit to change the originally staged content to unstaged, and finally stash pops back.
$ git commit -m "WIP"
$ git add .
$ git stash
$ git reset HEAD^
$ git stash pop --index 0
Note 1: This is used here pop
only because we want to keep idempotent as much as possible. Note 2: If you don't add it --index
you will mark the staged file as stored.
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 specific 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 of the contents of the working copy, but not all.
Check out 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 all the content you want to keep, reset the working copy, and reapply the preserved part.
$ 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
Branches
I pulled content from or to the wrong branch
Here's another use git reflog
case, finding what HEAD was pointing to before this erroneous 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
Finish.
I want to throw away my local commits so my branch is consistent with the remote
Make sure you are not pushing your content to the remote.
git status
will show how many commits you are ahead of 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 needed to commit to a new branch, but made the wrong commit 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^
Yes HEAD^1
shorthand, you can further reset by specifying what to set HEAD
.
Or, if you don't want to use it HEAD^
, find the hash of the commit you want to reset to ( git log
it can be done), and reset to that hash. Use to git push
sync content to remote.
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
Check out (checkout) the newly created branch to continue working:
(main)$ git checkout my-branch
I want to keep the whole file from another ref-ish
Suppose you are working on a prototype project (the original text is working spike (see note)), there are hundreds of content, each of which works very well. Now, you commit to a branch and save 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
), you care about keeping the whole file intact, and you want to separate a large commit into smaller ones.
Suppose you have:
branch
solution
, owning the prototype solution, leadingdevelop
the branch.Branch
develop
, where you apply some content of the prototype scheme.
I guess you can fix this by pulling the content into your branch:
(develop)$ git checkout solution -- file1.txt
This will get the contents of this file from the branch solution
into the 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 normally.
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 submitted several commits (commit) to the same branch, and these commits should be distributed in different branches
Suppose you have a main
branch, execute git log
, and you see that you made two commits:
(main)$ git log
commit e3851e817c451cc36f2e6f3049db528415e3c114
Author: Alex Lee <[email protected]>
Date: Tue Jul 22 15:39:27 2014 -0400
Bug #21 - Added CSRF protection
commit 5ea51731d150f7ddc4a365437931cd8be3bf3131
Author: Alex Lee <[email protected]>
Date: Tue Jul 22 15:39:12 2014 -0400
Bug #14 - Fixed spacing on title
commit a13b85e984171c6e2a1729bb061994525f626d14
Author: Aki Rose <[email protected]>
Date: Tue Jul 21 01:12:48 2014 -0400
First commit
Let's mark bugs with commit hash ( e3851e8
for #21, 5ea5173
for #14).
First, we main
reset the 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
(21)$
Next, we cherry-pick the commit for bug #21 into the current branch. This means we will apply (apply) this commit (commit), just this one commit (commit), directly above HEAD.
(21)$ git cherry-pick e3851e8
At this time, there may be conflicts here, see the conflict section of the interactive rebasing chapter to resolve conflicts.
Furthermore, we create a new branch for bug #14, also based on main
branch
(21)$ git checkout main
(main)$ git checkout -b 14
(14)$
Finally, for bug #14 execute cherry-pick
:
(14)$ git cherry-pick 5ea5173
I want to delete the local branch where the upstream branch was deleted
Once you've merged a pull request on github, you can delete the merged branch in your fork. If you are not going to continue working in this branch, it will be cleaner to delete the local copy of this branch, so that you will not fall into the chaos of working branches and a bunch of old branches (playing with Git in IDEA ) .
$ git fetch -p
I accidentally deleted my branch
If you regularly push to the remote, it should be safe most of the time, but sometimes it is possible to delete branches that have not been pushed to the remote. Let's start by creating 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 files 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 <[email protected]>
Date: Wed Jul 30 00:34:10 2014 +0200
foo.txt added
commit 69204cdf0acbab201619d95ad8295928e7f411d5
Author: Kate Hudson <[email protected]>
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 my-branch
the 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 remember reflog
, an updated version of the log, which stores the history of all actions in the warehouse (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 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 a remote daves
branch to a localdaves
(main)$ git checkout --track origin/daves
Branch daves set up to track remote branch daves from origin.
Switched to a new branch 'daves'
( short for --track
yes git checkout -b [branch] [remotename]/[branch]
)
In this way, you get a daves
local copy of the branch, and any updates pushed (pushed) can be seen remotely.
Rebasing and Merging
I want to undo the rebase/merge
You could merge or rebase the wrong branch, or fail to complete a rebase/merge in progress. Git will save the original HEAD in a variable called ORIG_HEAD when performing dangerous operations, so it is very easy to restore the branch to the state before rebase/merge.
(my-branch)$ git reset --hard ORIG_HEAD
I have already rebase, but I don't want to force push
Unfortunately, if you want to reflect these changes (changes) to the remote branch, you have to force push (force push). It is because you fast-forwarded the submission and changed the Git history, and the remote branch will not accept the changes (changes) unless it is forced to push (force push). This is one of the main reasons why many people use the merge workflow instead of the rebasing workflow, a force push by the developer can get large teams into trouble. Note when using it, a safe way to use rebase is not to reflect your changes (changes) to the remote branch, but to 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
Assume your working branch will do main
the pull-request for it. Normally you don't care about commit timestamps, you just want to combine all commits into 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 (interactive rebase):
(my-branch)$ git rebase -i main
If there is no other branch against, you will have to HEAD
rebase against your own. For example: you want to combine the last two commits (commit), you will rebase relative to HEAD~2
, combine the last three commits (commit), relative to HEAD~3
, and so on.
(main)$ git rebase -i HEAD~2
After you execute the interactive rebase command, you will see something like this 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 will not affect rebase.
Then, you can substitute any of the commands listed above pick
, and you can also delete a commit by deleting the corresponding line.
For example, if you want to keep the oldest (first) commit alone, and combine all the rest into the second , you should edit the The words are 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 one next to the second commit r
, or simply s
replace it with f
:
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 box 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 autocommitting, giving the user a chance to review and modify before committing. no-ff
It will leave evidence for the existence of the feature branch (feature branch), and keep the project history consistent (for more Git information, see How to complete the 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 (combine) the unpushed commit (unpushed commit)
Sometimes you have several work in progress commits before pushing the data upstream. At this time, you don't want to include the combinations that have been pushed, because others may already have commits that reference them.
(main)$ git rebase -i @{u}
This will generate an interactive rebase (interactive rebase), which will only list commits that have not been pushed. It is safe to reorder/fix/squash in this list.
Check if all commits on the branch have been merged
To check that 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 give you a list of all commits that are in one branch but not in the other, and a list of 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 (interactive rebase)
This rebase edit screen appears 'noop'
If you see something like this:
noop
This means that your rebase branch 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 rebase successfully, 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
there is a conflict. Open this file and find something similar to the following:
<<<<<<< HEAD
some code
=========
some code
>>>>>>> new-commit
You need to fix the difference between the newly submitted code (in the example, from the middle ==
line to new-commit
the place) and the new one.HEAD
Sometimes these merges are very complex and you should use the visual diff editor:
(main*)$ git mergetool -t opendiff
After you've resolved all conflicts and tested, git add
changed (changed) files, then git rebase --continue
continue with rebase.
(my-branch)$ git add README.md
(my-branch)$ git rebase --continue
If after resolving all conflicts, you get the same result as before submitting, you can execute it git rebase --skip
.
Anytime you want to end the whole rebase process and get back to the state of the branch before the rebase, you can do:
(my-branch)$ git rebase --abort
Stash
stage all changes
Staging all changes in your working directory
$ git stash
You can -u
exclude some files with
$ git stash -u
Temporarily store specified files
Suppose you only want to temporarily store 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
so you can list
see it when
$ git stash save <message>
or
$ git stash push -m <message>
Use a specific cache
First you can view your stash
records
$ git stash list
Then you can have apply
astash
$ git stash apply "stash@{n}"
Here, 'n' is stash
the position in the stack, the top one stash
will be 0
In addition, time stamps can also be used (if you can remember).
$ git stash apply "stash@{2.hours.ago}"
Preserve unstaged content when staging
You need to manually create one stash commit
and then use it 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 (tag)
If you want to restore a deleted tag (tag), you can follow the steps below: First, you need to find the unreachable tag (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.
Removed patch
If someone sends you a pull request on GitHub, but then deletes his own original fork, you won't be able to clone or use their commit git am
. In this case, it's best to manually review their commits, copy them to a new local branch, and commit.
After submitting, modify the author, see Changing the author. Then, apply the changes, and issue a new pull request.
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
Configuration
I want to add aliases to some Git commands
Under OS X and Linux, your Git configuration files are stored in ~/.gitconfig
. [alias]
I added some shortcut aliases (and some that I tend to misspell) in the section, as follows:
[alias]
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 warehouse that requires authorization. At this time, you can cache the username and password instead of entering it every time you push/pull (push/pull). 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 did wrong
You messed things up: you 重置(reset)
broke something, or you merged the wrong branch, or you couldn't find your own commits after a push. There are times when you've been doing great all along, but you want to go back to something you were before.
This is git reflog
the purpose, reflog
to record any changes to the tip of a branch, even if that tip is not referenced by any branch or tag. Basically, every time HEAD changes, a new record is added to it reflog
. Unfortunately, this only works on local branches, and it only tracks actions (for example, any changes to an unlogged file will not be tracked).
(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 then back again. There, there is also a hard reset to an older commit. The newest actions appear at the top for HEAD@{0}
identification.
If it turns out that you accidentally moved back (move back) the commit (commit), the reflog will contain the commit pointed to on main before you accidentally moved back (0254ea7).
$ git reset --hard 0254ea7
Then use git reset to change the main back to the previous commit, which provides a safety net in case the history is accidentally changed.
作者:小富
https://blog.csdn.net/xinzhifu1/article/details/123271097