RESOURCES
- Clone Specific Branch -2- Specific Folder
-
git fetch origin && git reset --hard origin/master && git clean -f -d branch for yourself - you can see the branch names at: https://repositoryaddress.com/etc/-/branches git clone -b
git clone -b trenton-ducatti https://git.reoop.com/infostuff/site-site.git foldersmp cd into new folder then create a new branch git checkout -b git checkout -b smpnewbranch ++++++ git remote show origin shows remote and local branches with tracking info. ++++++++ git branch --set-upstream-to=origin/trenton-ducatti smptrentonsmlpush git push --set-upstream origin smptrentonsmlpush The upstream branch of your current branch does not match the name of your current branch. To push to the upstream branch on the remote, use git push origin HEAD:trenton-ducatti
-
Create New Local Branch
// Example for creating a new branch named myNewBranch
git checkout -b myNewBranch
lock local branch to origin
- git branch –set-upstream-to=origin/ORIGINbranch LOCALbranch
- No CLI / COMMAND LINE TOOLS: Medium Article |
sudo xcode-select --reset
-
- list all branches in repos
-
git branch -a
git add and commit
git reset without the –hard option resets the commit history, but not the files. With the –hard option the files in working tree are also reset. (credited user)
If you wish to commit that state so that the remote repository also points to the rolled back commit do: git push
The second option for me did not run: I had to do git push -f
If you haven’t made any other changes after that, you can follow this steps:
Run git reflog. This will give you a log of the actions done by you on the repo Pick the log just before the pull. If it is the second last commit you can run
git reset –hard HEAD@{2}
to restore your repo to a state just before you pulled your repo
https://docs.gitlab.com/13.12/ee/topics/git/numerous_undo_possibilities_in_git/
Undo possibilities in Git ALL TIERS
Nothing in Git is deleted, so when you work in Git, you can undo your work.
All version control systems have options for undoing work. However, because of the de-centralized nature of Git, these options are multiplied. The actions you take are based on the stage of development you are in.
For more information about working with Git and GitLab:
- Learn why North Western Mutual chose GitLab for their enterprise source code management.
- Learn how to get started with Git.
- For more advanced examples, refer to the Git book.
When you can undo changes
In the standard Git workflow:
- You create or edit a file. It starts in the unstaged state. If it’s new, it is not yet tracked by Git.
- You add the file to your local repository (
git add
), which puts the file into the staged state. - You commit the file to your local repository (
git commit
). - You can then share the file with other developers, by committing to a remote repository (
git push
).
You can undo changes at any point in this workflow:
When you’re working locally and haven’t yet pushed to a remote repository.
When you have already pushed to a remote repository and you want to:
- Keep the history intact (preferred).
- Change the history (requires coordination with team and force pushes).
Undo local changes
Until you push your changes to a remote repository, changes you make in Git are only in your local development environment.
Undo unstaged local changes
When you make a change, but have not yet staged it, you can undo your work.
Confirm that the file is unstaged (that you did not use
git add <file>
) by runninggit status
:$ git status On branch main Your branch is up-to-date with 'origin/main'. 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: <file> no changes added to commit (use "git add" and/or "git commit -a")
Choose an option and undo your changes:
To overwrite local changes:
git checkout -- <file>
To save local changes so you can re-use them later:
git stash
To discard local changes to all files, permanently:
git reset --hard
Undo staged local changes
If you added a file to staging, you can undo it.
Confirm that the file is staged (that you used
git add <file>
) by runninggit status
:$ git status On branch main Your branch is up-to-date with 'origin/main'. Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: <file>
Choose an option and undo your changes:
To unstage the file but keep your changes:
git restore --staged <file>
To unstage everything but keep your changes:
git reset
To unstage the file to current commit (HEAD):
git reset HEAD <file>
To discard all local changes, but save them for later:
git stash
To discard everything permanently:
git reset --hard
Quickly save local changes
If you want to change to another branch, you can use git stash
.
From the branch where you want to save your work, type
git stash
.Swap to another branch (
git checkout <branchname>
).Commit, push, and test.
Return to the branch where you want to resume your changes.
Use
git stash list
to list all previously stashed commits.Run a version of
git stash
:- Use
git stash pop
to redo previously stashed changes and remove them from stashed list. - Use
git stash apply
to redo previously stashed changes, but keep them on stashed list.
- Use
Undo committed local changes
When you commit to your local repository (git commit
), the version control system records your changes. Because you did not push to a remote repository yet, your changes are not public (or shared with other developers). At this point, you can undo your changes.
Undo staged local changes without modifying history
You can revert a commit while retaining the commit history.
This example uses five commits A
,B
,C
,D
,E
, which were committed in order: A-B-C-D-E
. The commit you want to undo is B
.
Find the commit SHA of the commit you want to revert to. To look through a log of commits, type
git log
.Choose an option and undo your changes:
To swap additions and deletions changes introduced by commit
B
:git revert <commit-B-SHA>
To undo changes on a single file or directory from commit
B
, but retain them in the staged state:git checkout <commit-B-SHA> <file>
To undo changes on a single file or directory from commit
B
, but retain them in the unstaged state:git reset <commit-B-SHA> <file>
Undo multiple committed changes
You can recover from multiple commits. For example, if you have done commits A-B-C-D
on your feature branch and then realize that C
and D
are wrong.
To recover from multiple incorrect commits:
Check out the last correct commit. In this example,
B
.git checkout <commit-B-SHA>
Create a new branch.
git checkout -b new-path-of-feature
Add, push, and commit your changes.
The commits are now A-B-C-D-E
.
Alternatively, with GitLab, you can cherry-pick that commit into a new merge request.
Another solution is to reset to B
and commit E
. However, this solution results in A-B-E
, which clashes with what other developers have locally.
Undo staged local changes with history modification
You can rewrite history in Git, but you should avoid it, because it can cause problems when multiple developers are contributing to the same codebase.
There is one command for history modification and that is git rebase
. Command provides interactive mode (-i
flag) which enables you to:
- reword commit messages (there is also
git commit --amend
for editing last commit message). - edit the commit content (changes introduced by commit) and message.
- squash multiple commits into a single one, and have a custom or aggregated commit message.
- drop commits – delete them.
- and few more options.
Let us check few examples. Again there are commits A-B-C-D
where you want to delete commit B
.
Rebase the range from current commit D to A:
git rebase -i A
Command opens your favorite editor where you write
drop
in front of commitB
, but you leave defaultpick
with all other commits. Save and exit the editor to perform a rebase. Remember: if you want to cancel delete whole file content before saving and exiting the editor
In case you want to modify something introduced in commit B
.
Rebase the range from current commit D to A:
git rebase -i A
Command opens your favorite text editor where you write
edit
in front of commitB
, but leave defaultpick
with all other commits. Save and exit the editor to perform a rebase.Now do your edits and commit changes:
git commit -a
You can find some more examples in the section explaining how to modify history.
Redoing the undo
Sometimes you realize that the changes you undid were useful and you want them back. Well because of first paragraph you are in luck. Command git reflog
enables you to recall detached local commits by referencing or applying them via commit ID. Although, do not expect to see really old commits in reflog, because Git regularly cleans the commits which are unreachable by branches or tags.
To view repository history and to track older commits you can use below command:
$ git reflog show
# Example output:
b673187 HEAD@{4}: merge 6e43d5987921bde189640cc1e37661f7f75c9c0b: Merge made by the 'recursive' strategy.
eb37e74 HEAD@{5}: rebase -i (finish): returning to refs/heads/master
eb37e74 HEAD@{6}: rebase -i (pick): Commit C
97436c6 HEAD@{7}: rebase -i (start): checkout 97436c6eec6396c63856c19b6a96372705b08b1b
...
88f1867 HEAD@{12}: commit: Commit D
97436c6 HEAD@{13}: checkout: moving from 97436c6eec6396c63856c19b6a96372705b08b1b to test
97436c6 HEAD@{14}: checkout: moving from master to 97436c6
05cc326 HEAD@{15}: commit: Commit C
6e43d59 HEAD@{16}: commit: Commit B
Output of command shows repository history. In first column there is commit ID, in following column, number next to HEAD
indicates how many commits ago something was made, after that indicator of action that was made (commit, rebase, merge, …) and then on end description of that action.
Undo remote changes without changing history
This topic is roughly same as modifying committed local changes without modifying history. It should be the preferred way of undoing changes on any remote repository or public branch. Keep in mind that branching is the best solution when you want to retain the history of faulty development, yet start anew from certain point.
Branching enables you to include the existing changes in new development (by merging) and it also provides a clear timeline and development structure.

If you want to revert changes introduced in certain commit-id
, you can revert that commit-id
(swap additions and deletions) in newly created commit: You can do this with
git revert commit-id
or creating a new branch:
git checkout commit-id
git checkout -b new-path-of-feature
Undo remote changes with modifying history
This is useful when you want to hide certain things – like secret keys, passwords, and SSH keys. It is and should not be used to hide mistakes, as it makes it harder to debug in case there are some other bugs. The main reason for this is that you loose the real development progress. Keep in mind that, even with modified history, commits are just detached and can still be accessed through commit ID – at least until all repositories perform the automated cleanup of detached commits.

Where modifying history is generally acceptable
Modified history breaks the development chain of other developers, as changed history does not have matching commit IDs. For that reason it should not be used on any public branch or on branch that might be used by other developers. When contributing to big open source repositories (for example, GitLab itself), it is acceptable to squash commits into a single one, to present a nicer history of your contribution.
Keep in mind that this also removes the comments attached to certain commits in merge requests, so if you need to retain traceability in GitLab, then modifying history is not acceptable.
A feature branch of a merge request is a public branch and might be used by other developers, but project process and rules might allow or require you to use git rebase
(command that changes history) to reduce number of displayed commits on target branch after reviews are done (for example GitLab). There is a git merge --squash
command which does exactly that (squashes commits on feature-branch to a single commit on target branch at merge).
Never modify the commit history of master
or shared branch.
How modifying history is done
After you know what you want to modify (how far in history or how which range of old commits), use git rebase -i commit-id
. This command displays all the commits from current version to chosen commit ID and allow modification, squashing, deletion of that commits.
$ git rebase -i commit1-id..commit3-id
pick <commit1-id> <commit1-commit-message>
pick <commit2-id> <commit2-commit-message>
pick <commit3-id> <commit3-commit-message>
# Rebase commit1-id..commit3-id onto <commit4-id> (3 command(s))
#
# 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
# d, drop = remove commit
#
# 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
The comment from the output clearly states that, if you decide to abort, don’t just close your editor (as that modifies history), but remove all uncommented lines and save.
Use git rebase
carefully on shared and remote branches, but rest assured: nothing is broken until you push back to the remote repository (so you can freely explore the different outcomes locally).
# Modify history from commit-id to HEAD (current commit)
git rebase -i commit-id
Deleting sensitive information from commits
Git also enables you to delete sensitive information from your past commits and it does modify history in the progress. That is why we have included it in this section and not as a standalone topic. To do so, you should run the git filter-branch
, which enables you to rewrite history with certain filters. This command uses rebase to modify history and if you want to remove certain file from history altogether use:
git filter-branch --tree-filter 'rm filename' HEAD
Because git filter-branch
command might be slow on big repositories, there are tools that can use some of Git specifics to enable faster execution of common tasks (which is exactly what removing sensitive information file is about). An alternative is the open source community-maintained tool BFG. Keep in mind that these tools are faster because they do not provide the same feature set as git filter-branch
does, but focus on specific use cases.
Refer Reduce repository size page to know more about purging files from repository history & GitLab storage.
Set upstream branch for an existing remote branch
In some cases, you may choose to link your local branches to existing remote branches that you just pulled or cloned from the main repository.
Let’s say for example that you pulled the “dev” branch located on the “origin” remote.
As a consequence, the tracking branch is named “origin/dev”.
Force – Remote / Local Matching
Setting your branch to exactly match the remote branch can be done in two steps:
git fetch origin
git reset --hard origin/master
Update @2020 (if you have main
branch instead of master
in remote repo)
git fetch origin
git reset --hard origin/main
If you want to save your current branch's state before doing this (just in case), you can do:
git commit -a -m "Saving my work, just in case"
git branch my-saved-work
Now your work is saved on the branch "my-saved-work" in case you decide you want it back (or want to look at it later or diff it against your updated branch).
Note that the first example assumes that the remote repo's name is "origin" and that the branch named "master" in the remote repo matches the currently checked-out branch in your local repo.
BTW, this situation that you're in looks an awful lot like a common case where a push has been done into the currently checked out branch of a non-bare repository. Did you recently push into your local repo? If not, then no worries — something else must have caused these files to unexpectedly end up modified. Otherwise, you should be aware that it's not recommended to push into a non-bare repository (and not into the currently checked-out branch, in particular).
git push
# If its your first push
git push -u origin BRANCH
# Otherwise
git push origin BRANCH
git new branch push to remoteShell/Bash
git push -u origin
Source:stackoverflow.com
Image result for git push repo
In order to push a Git branch to remote, you need to execute the “git push” command and specify the remote as well as the branch name to be pushed. If you are not already on the branch that you want to push, you can execute the “git checkout” command to switch to your branch.
git pull
How to Clone a Single Branch in Git
https://www.w3docs.com/snippets/git/how-to-clone-a-single-branch-in-git.html
Introduction to Git Clone
Git allows you to manage and version your project(s) in a "repository". This repository is stored on a web-based hosting service for version control, like GitHub.
You can then clone this repository to your local machine and have all the files and branches locally (I'll explain more about branches soon).
For example, you can clone freeCodeCamp's repository with SSH like so:
git clone git@github.com:freeCodeCamp/freeCodeCamp.git
Introduction to Git Branches
When working on a project, you will likely have different features. And multiple contributors will be working on this project and its features.
Branches allow you to create a "playground" with the same files in the master
branch. You can use this branch to build independent features, test new features, make breaking changes, create fixes, write docs or try out ideas without breaking or affecting the production code. When you're done, you merge the branch into the production master
branch.
Branching is a core concept in Git which is also used in GitHub to manage workflows of different versions of one project. The master
branch is always the default branch in a repository that is most often considered "production and deployable code". New branches like passwordless-auth
or refactor-signup-ux
can be created from the master
branch.
All branches in freeCodeCamp's repository
How to Clone Git Branches
While you can clone repositories with the git clone
command, keep in mind that this clones the branch and the remote HEAD
. This is usually master
by default and includes all other branches in the repository.
So when you clone a repository, you clone the master
and all other branches. This means you will have to checkout another branch yourself.
Let's say your task on a project is to work on a feature to add passwordless authentication to a user dashboard. And this feature is in the passwordless-auth
branch.
You really don't need the master
branch since your "feature branch" will be merged into master
afterward. How then do you clone this passwordless-auth
branch without fetching all other branches with "a bunch of files you don't need"?
I created this sample repository to explain this. This repository holds a simple blog built with Nextjs and has four dummy branches:
- master
- dev
- staging
- passwordless-auth
In Nextjs, any file inside the folder pages/api
is mapped to the /api/*
path and will be treated as an API endpoint instead of a page
. In our repository, I have created different dummy APIs in this directory to make each branch different.
The master
branch holds the file pages/api/hello.js while passwordless-auth
holds the file pages/api/auth.js. Each file just returns a dummy text response. See master
's hello API response here (with a special message for you ?).
Let's clone the repository:
git clone git@github.com:BolajiAyodeji/nextjs-blog.git
This gives us access to all branches in this repository and you can easily toggle between each to see each version and its files.
List all Branches in Repo
git branch -a
Wondering where the remotes/origin/.. branches came from?
When you clone a repository, you pull data from a repository on the internet or an internal server known as the remote. The word origin is an alias created by your Git to replace the remote URL (you can change or specify another alias if you want).
These remotes/origin/.. branches point you back to the origin repository you cloned from the internet so you can still perform pull/push from the origin.
So when you clone master
onto your machine, remotes/origin/master
is the original master
branch on the internet, and master
is on your local machine. So you will pull/push from and to the remotes/origin/master
.
In summary Remote is the URL that points you to the repository on the internet while Origin is an alias for this remote URL.
How to Clone a Specific Branch
Now let's clone a specific branch from our demo repository. There are two ways to clone a specific branch. You can either:
- Clone the repository, fetch all branches, and checkout to a specific branch immediately.
- Clone the repository and fetch only a single branch.
Option One
git clone --branch <branchname> <remote-repo-url>
or
git clone -b <branchname> <remote-repo-url>
Here -b is just an alias for –branch
With this, you fetch all the branches in the repository, checkout to the one you specified, and the specific branch becomes the configured local branch for git push
and git pull
. But you still fetched all files from each branch. This might not be what you want right? ?
Let's test it:
git clone -b passwordless-auth git@github.com:BolajiAyodeji/nextjs-blog.git
This automatically configures passwordless-auth
as the local branch but still tracks other branches.
Option Two
git clone --branch <branchname> --single-branch <remote-repo-url>
or
git clone -b <branchname> --single-branch <remote-repo-url>
Here -b is just an alias for –branch
This performs the same action as option one, except that the --single-branch
option was introduced in Git version 1.7.10 and later. It allows you to only fetch files from the specified branch without fetching other branches.
Let's test it:
git clone -b passwordless-auth --single-branch git@github.com:BolajiAyodeji/nextjs-blog.git
This automatically configures passwordless-auth
as the local branch and only tracks this branch.
If you run cd pages/api
you'll find the auth.js
file in the passwordless-auth
branch as expected from the previous setup.
Conclusion
You might be running out of internet or storage space but you need to work on a task in a specific branch. Or you might want to clone a specific branch with limited files for various reasons. Fortunately, Git provides you the flexibility to do this. Flex your muscles and try it out, there's much more "Git" to learn.
Clone branch into specific folder
https://stackoverflow.com/questions/651038/how-do-you-clone-a-git-repository-into-a-specific-folder
Option A:
git clone git@github.com:whatever folder-name
Ergo, for right here
use:
git clone git@github.com:whatever .
Option B:
Move the .git
folder, too. Note that the .git
folder is hidden in most graphical file explorers, so be sure to show hidden files.
mv /where/it/is/right/now/* /where/I/want/it/
mv /where/it/is/right/now/.* /where/I/want/it/
The first line grabs all normal files, the second line grabs dot-files. It is also possibe to do it in one line by enabling dotglob (i.e. shopt -s dotglob
) but that is probably a bad solution if you are asking the question this answer answers.
Better yet:
Keep your working copy somewhere else, and create a symbolic link. Like this:
ln -s /where/it/is/right/now /the/path/I/want/to/use
For your case this would be something like:
ln -sfn /opt/projectA/prod/public /httpdocs/public
Which easily could be changed to test if you wanted it, i.e.:
ln -sfn /opt/projectA/test/public /httpdocs/public
without moving files around. Added -fn
in case someone is copying these lines (-f
is force, -n
avoid some often unwanted interactions with already and non-existing links).
If you just want it to work, use Option A, if someone else is going to look at what you have done, use Option C.
Create new branch locally
// Example for creating a new branch named myNewBranch
git checkout -b myNewBranch
https://www.atlassian.com/git/tutorials/using-branches
https://www.atlassian.com/git/tutorials/learn-git-with-bitbucket-cloud
Git Branch
This document is an in-depth review of the git branch
command and a discussion of the overall Git branching model. Branching is a feature available in most modern version control systems. Branching in other VCS's can be an expensive operation in both time and disk space. In Git, branches are a part of your everyday development process. Git branches are effectively a pointer to a snapshot of your changes. When you want to add a new feature or fix a bug—no matter how big or how small—you spawn a new branch to encapsulate your changes. This makes it harder for unstable code to get merged into the main code base, and it gives you the chance to clean up your future's history before merging it into the main branch.
The diagram above visualizes a repository with two isolated lines of development, one for a little feature, and one for a longer-running feature. By developing them in branches, it’s not only possible to work on both of them in parallel, but it also keeps the main master
branch free from questionable code.
The implementation behind Git branches is much more lightweight than other version control system models. Instead of copying files from directory to directory, Git stores a branch as a reference to a commit. In this sense, a branch represents the tip of a series of commits—it's not a container for commits. The history for a branch is extrapolated through the commit relationships.
As you read, remember that Git branches aren't like SVN branches. Whereas SVN branches are only used to capture the occasional large-scale development effort, Git branches are an integral part of your everyday workflow. The following content will expand on the internal Git branching architecture.
How it works
A branch represents an independent line of development. Branches serve as an abstraction for the edit/stage/commit process. You can think of them as a way to request a brand new working directory, staging area, and project history. New commits are recorded in the history for the current branch, which results in a fork in the history of the project.
The git branch
command lets you create, list, rename, and delete branches. It doesn’t let you switch between branches or put a forked history back together again. For this reason, git branch
is tightly integrated with the git checkout
and git merge
commands.
Common Options
git branch
List all of the branches in your repository. This is synonymous with git branch --list.
git branch <branch>
Create a new branch called <branch>
. This does not check out the new branch.
git branch -d <branch>
Delete the specified branch. This is a “safe” operation in that Git prevents you from deleting the branch if it has unmerged changes.
git branch -D <branch>
Force delete the specified branch, even if it has unmerged changes. This is the command to use if you want to permanently throw away all of the commits associated with a particular line of development.
git branch -m <branch>
Rename the current branch to <branch>
.
git branch -a
List all remote branches.
Creating Branches
It's important to understand that branches are just pointers to commits. When you create a branch, all Git needs to do is create a new pointer, it doesn’t change the repository in any other way. If you start with a repository that looks like this:
Then, you create a branch using the following command:
git branch crazy-experiment
The repository history remains unchanged. All you get is a new pointer to the current commit:
Note that this only creates the new branch. To start adding commits to it, you need to select it with git checkout
, and then use the standard git add
and git commit
commands.
Creating remote branches
So far these examples have all demonstrated local branch operations. The git branch
command also works on remote branches. In order to operate on remote branches, a remote repo must first be configured and added to the local repo config.
$ git remote add new-remote-repo https://bitbucket.com/user/repo.git
# Add remote repo to local repo config
$ git push <new-remote-repo> crazy-experiment~
# pushes the crazy-experiment branch to new-remote-repo
This command will push a copy of the local branch crazy-experiment
to the remote repo <remote>.
Deleting Branches
Once you’ve finished working on a branch and have merged it into the main code base, you’re free to delete the branch without losing any history:
git branch -d crazy-experiment
However, if the branch hasn’t been merged, the above command will output an error message:
error: The branch 'crazy-experiment' is not fully merged. If you are sure you want to delete it, run 'git branch -D crazy-experiment'.
This protects you from losing access to that entire line of development. If you really want to delete the branch (e.g., it’s a failed experiment), you can use the capital -D
flag:
git branch -D crazy-experiment
This deletes the branch regardless of its status and without warnings, so use it judiciously.
The previous commands will delete a local copy of a branch. The branch may still exist in remote repos. To delete a remote branch execute the following.
git push origin --delete crazy-experiment
Or
git push origin :crazy-experiment
This will push a delete signal to the remote origin repository that triggers a delete of the remote crazy-experiment
branch.
Summary
In this document we discussed Git's branching behavior and the git branch
command. The git branch
commands primary functions are to create, list, rename and delete branches. To operate further on the resulting branches the command is commonly used with other commands like git checkout
. Learn more about git checkout
branch operations; such as switching branches and merging branches, on the git checkout
page.
Compared to other VCSs, Git's branch operations are inexpensive and frequently used. This flexibility enables powerful Git workflow customization. For more info on Git workflows visit our extended workflow discussion pages: The Feature Branch Workflow, GitFlow Workflow, and Forking Workflow.
Ready to try branching?
Try this interactive tutorial.
How to git reset hard and push
When working locally, it’s not exactly clear what happens when you git reset to a previous commit and push those commits to a remote repository. So to demonstrate exactly what happens when you git reset and push, I’m first going to create an empty, remote GitHub repository named git-reset-explained. It will contain nothing but a readme.md file, an MIT licence, a .gitignore file and a single commit.
Remote repository for git reset and push.
Cloning the git-reset-explained repo
With the remote GitHub repository created, I will locally clone the repo and begin working inside of it.
/c/ git reset hard and push /
$ git clone https://github.com/cameronmcnz/git-reset-explained.git
Cloning into 'git-reset-explained'...
$ cd git*
/c/ git reset hard and push / git reset explained
Creating a local commit history
From within the cloned repo, I will create five new files, adding a new commit each time.
/c/ git reset hard and push / git reset explained
$ touch alpha.html
$ git add . & git commit -m "Local commit #1"
$ touch beta.html
$ git add . & git commit -m "Local commit #2"
$ touch charlie.html
$ git add . & git commit -m "Local commit #3"
$ touch depeche.html
$ git add . & git commit -m "Local commit #4"
$ touch enid.html
$ git add . & git commit -m "Local commit #5"
A call to the reflog shows the history of HEAD as the git commit commands were issued:
/c/ git reset hard and push / git reset explained
$ git reflog
014df6a (HEAD -> master) HEAD@{0}: commit: Local commit #5
6237772 HEAD@{1}: commit: Local commit #4
593794d HEAD@{2}: commit: Local commit #3
b1a6865 HEAD@{3}: commit: Local commit #2
8a3358e HEAD@{4}: commit: Local commit #1
d072c0a (origin/master, origin/HEAD) HEAD@{5}: clone
git reset to a previous commit
Now if I was to perform a hard git reset and shift HEAD to the third local commit, commits 4 and 5 should disappear, right? The git reset should remove those commits from my commit history and take me right back to the reset point, right? Let’s see what actually happens when we issue the command to git reset local commits.
/c/ git reset hard and push / git reset explained
$ git reset --hard 593794d
HEAD is now at 593794d Local commit #3
Now let’s see what the reflog looks like:
/c/ git reset hard and push / git reset explained
$ git reflog
593794d (HEAD -> master) HEAD@{0} reset to 593794d
014df6a HEAD@{1}: commit: Local commit #5
6237772 HEAD@{2}: commit: Local commit #4
593794d (HEAD -> master) HEAD@{3}: commit: Local commit #3
b1a6865 HEAD@{4}: commit: Local commit #2
8a3358e HEAD@{5}: commit: Local commit #1
d072c0a (origin/master, origin/HEAD) HEAD@{6} clone
git reset hard and push
As you can see from the git reflog command, commits 014df6a and 6237772 are still hanging around. When you git reset local commits, those commits don’t disappear.
Knowing Git’s propensity to store everything, this isn’t a particularly unexpected result. The real question is, what would happen if you were to git reset to a previous commit and push to a remote repository? Would the two local commits git leapfrogged over get pushed as well, or would they remain isolated locally? To find out, we simply push to the remote origin:
/c/ git reset hard and push / git reset explained
$ git push origin
Counting objects: 7, done.
To github.com/cameronmcnz/git-reset-explained.git
d072c0a..593794d master -> master
After the push, when we look at the commit history on GitHub, we notice there are only four commits, the server-side commit that created the GitHub repository, and the three local commits that we published. When the git reset and push happened, the fourth and fifth local commits were not pushed to the server, essentially deleting any history of them ever existing.
Result of a git reset hard and remote push.
git reset vs revert
So what did we learn? Well, that when we git reset to a previous commit and push to a remote repository, no trace of the undone commits are published. That’s in stark contrast to a git revert in which the revert command itself creates a new commit, and none of the past commit history is lost. So if you ever want to undo a previous commit with Git, reset is the right Git command to use, not revert.
Become a Git power user
Want to become a Git power user? Take a look at the following Git articles and tutorials
- How to do a Git clean up of branches and commits
- Learn to rebase onto master and rebase from the master branch
- Squash all Git commits on a branch down to one
- Shelve your changes with Git stash pop and apply
- Easily explain the Git vs GitHub difference
- Add a shallow git clone of depth 1 do your Jenkins jobs
- Set up a local Git server with a bare Git repo
- The Git fork command explained
GitLab merge master to branch options
There are two acceptable ways with GitLab to merge the master branch into another. Which approach a developer chooses will depend whether the branch they want master to merge into is protected or not.
- If the developer wants to merge master into a branch that’s protected, they must perform a GitLab merge request.
- If the developer wants to merge master into a branch that’s unprotected, the easiest approach is to do a merge and push combination on the client machine.
The remote GitLab branch to delete is name feature_fun.
Merge master into unprotected GitLab branch
In the current state of my GitLab repository, I haven’t observed many GitFlow best practices and as a result, it has left the unprotected fun_feature branch several commits behind the master. The first GitLab merge master into a branch will be into the fun_feature branch. We will perform this merge master entirely on the client side and won’t involve the GitLab GUI in the process.
The steps to merge master into any branch are:
- Open a Terminal window on the client machine
- Switch to the feature branch
- Use git to merge master into the branch
- View a directory listing to validate files from master have been moved to the feature branch
- View the Git reflog to validate that a master merge commit is registered
- Push the merged feature branch back to the GitLab server
- View the feature branch in the GitLab web app to validate the merge from master to branch is reflected on the server
GitLab merge master commands
A developer can use the following commands to merge master into any branch in GitLab:
git checkout fun_feature
git merge master
ls
git reflog
git push origin fun_feature
GitLab master to branch merge request
In a previous GitLab tutorial, both the develop branch and the hotfix branch was merged into master. That sequence of events somewhat violates proper GitFlow rules, because those branches should’ve been merged into the release branch first. As a result, the release branch is out of sync with master. I can rectify this problem with a GitLab merge master into this branch. When the merge is complete, the release and master branch will be in sync.
Since the release branch is protected, the process is a little different. If a developer wants to merge the GitLab master into a protected branch, the proper approach is to perform a merge request. Simply log into the GitLab web app, choose the option to create a GitLab merge request, specify the master branch as the source and the protected branch as the target of the merge.
The merge request can be used to have GitLab merge master in a branch that is protected.
After the merge request is submitted, the assignee will be notified of the request the next time they log in. If the merge request is approved without conflict, the GitLab master will merge into the branch, and both the master and release branches will be in sync.
The source code and sample project used for these examples can be found on the gitlab-made-easy project page on GitLab.
How to git reset hard and push
When working locally, it’s not exactly clear what happens when you git reset to a previous commit and push those commits to a remote repository. So to demonstrate exactly what happens when you git reset and push, I’m first going to create an empty, remote GitHub repository named git-reset-explained. It will contain nothing but a readme.md file, an MIT licence, a .gitignore file and a single commit.
Remote repository for git reset and push.
Cloning the git-reset-explained repo
With the remote GitHub repository created, I will locally clone the repo and begin working inside of it.
/c/ git reset hard and push /
$ git clone https://github.com/cameronmcnz/git-reset-explained.git
Cloning into 'git-reset-explained'...
$ cd git*
/c/ git reset hard and push / git reset explained
Creating a local commit history
From within the cloned repo, I will create five new files, adding a new commit each time.
/c/ git reset hard and push / git reset explained
$ touch alpha.html
$ git add . & git commit -m "Local commit #1"
$ touch beta.html
$ git add . & git commit -m "Local commit #2"
$ touch charlie.html
$ git add . & git commit -m "Local commit #3"
$ touch depeche.html
$ git add . & git commit -m "Local commit #4"
$ touch enid.html
$ git add . & git commit -m "Local commit #5"
A call to the reflog shows the history of HEAD as the git commit commands were issued:
/c/ git reset hard and push / git reset explained
$ git reflog
014df6a (HEAD -> master) HEAD@{0}: commit: Local commit #5
6237772 HEAD@{1}: commit: Local commit #4
593794d HEAD@{2}: commit: Local commit #3
b1a6865 HEAD@{3}: commit: Local commit #2
8a3358e HEAD@{4}: commit: Local commit #1
d072c0a (origin/master, origin/HEAD) HEAD@{5}: clone
git reset to a previous commit
Now if I was to perform a hard git reset and shift HEAD to the third local commit, commits 4 and 5 should disappear, right? The git reset should remove those commits from my commit history and take me right back to the reset point, right? Let’s see what actually happens when we issue the command to git reset local commits.
/c/ git reset hard and push / git reset explained
$ git reset --hard 593794d
HEAD is now at 593794d Local commit #3
Now let’s see what the reflog looks like:
/c/ git reset hard and push / git reset explained
$ git reflog
593794d (HEAD -> master) HEAD@{0} reset to 593794d
014df6a HEAD@{1}: commit: Local commit #5
6237772 HEAD@{2}: commit: Local commit #4
593794d (HEAD -> master) HEAD@{3}: commit: Local commit #3
b1a6865 HEAD@{4}: commit: Local commit #2
8a3358e HEAD@{5}: commit: Local commit #1
d072c0a (origin/master, origin/HEAD) HEAD@{6} clone
git reset hard and push
As you can see from the git reflog command, commits 014df6a and 6237772 are still hanging around. When you git reset local commits, those commits don’t disappear.
Knowing Git’s propensity to store everything, this isn’t a particularly unexpected result. The real question is, what would happen if you were to git reset to a previous commit and push to a remote repository? Would the two local commits git leapfrogged over get pushed as well, or would they remain isolated locally? To find out, we simply push to the remote origin:
/c/ git reset hard and push / git reset explained
$ git push origin
Counting objects: 7, done.
To github.com/cameronmcnz/git-reset-explained.git
d072c0a..593794d master -> master
After the push, when we look at the commit history on GitHub, we notice there are only four commits, the server-side commit that created the GitHub repository, and the three local commits that we published. When the git reset and push happened, the fourth and fifth local commits were not pushed to the server, essentially deleting any history of them ever existing.
Result of a git reset hard and remote push.
git reset vs revert
So what did we learn? Well, that when we git reset to a previous commit and push to a remote repository, no trace of the undone commits are published. That’s in stark contrast to a git revert in which the revert command itself creates a new commit, and none of the past commit history is lost. So if you ever want to undo a previous commit with Git, reset is the right Git command to use, not revert.
Become a Git power user
Want to become a Git power user? Take a look at the following Git articles and tutorials
- How to do a Git clean up of branches and commits
- Learn to rebase onto master and rebase from the master branch
- Squash all Git commits on a branch down to one
- Shelve your changes with Git stash pop and apply
- Easily explain the Git vs GitHub difference
- Add a shallow git clone of depth 1 do your Jenkins jobs
- Set up a local Git server with a bare Git repo
- The Git fork command explained
Rollback commits ALL TIERS
Undo Commits
Undo last commit putting everything back into the staging area:
git reset --soft HEAD^
Add files and change message with:
git commit --amend -m "New Message"
Undo last and remove changes:
git reset --hard HEAD^
Same as last one but for two commits back:
git reset --hard HEAD^^
Don’t reset after pushing
Reset Workflow
- Edit file again ‘edit_this_file.rb’
- Check status
- Add and commit with wrong message
- Check log
- Amend commit
- Check log
- Soft reset
- Check log
- Pull for updates
- Push changes
Commands
# Change file edit_this_file.rb
git status
git commit -am "kjkfjkg"
git log
git commit --amend -m "New comment added"
git log
git reset --soft HEAD^
git log
git pull origin master
git push origin master
Note
git revert
vsgit reset
- Reset removes the commit while revert removes the changes but leaves the commit
- Revert is safer considering we can revert a revert
# Changed file
git commit -am "bug introduced"
git revert HEAD
# New commit created reverting changes
# Now we want to re apply the reverted commit
git log # take hash from the revert commit
git revert <rev commit hash>
# reverted commit is back (new commit created again)
Undo a commit & redo
$ git commit -m "Something terribly misguided" # (0: Your Accident)
$ git reset HEAD~ # (1)
[ edit files as necessary ] # (2)
$ git add . # (3)
$ git commit -c ORIG_HEAD # (4)
- This command is responsible for the undo. It will undo your last commit while leaving your working tree (the state of your files on disk) untouched. You'll need to add them again before you can commit them again).
- Make corrections to working tree files.
git add
anything that you want to include in your new commit.- Commit the changes, reusing the old commit message.
reset
copied the old head to.git/ORIG_HEAD
;commit
with-c ORIG_HEAD
will open an editor, which initially contains the log message from the old commit and allows you to edit it. If you do not need to edit the message, you could use the-C
option.
Alternatively, to edit the previous commit (or just its commit message), commit --amend
will add changes within the current index to the previous commit.
To remove (not revert) a commit that has been pushed to the server, rewriting history with git push origin master --force
is necessary.
Further Reading
How can I move HEAD back to a previous location? (Detached head) & Undo commits
The above answer will show you git reflog
, which you can use to determine the SHA-1 for the commit to which you wish to revert. Once you have this value, use the sequence of commands as explained above.
HEAD~
is the same as HEAD~1
. The article What is the HEAD in git? is helpful if you want to uncommit multiple commits.
Follow
community wiki
47 revs, 39 users 15% Mark Amery
522
And if the commit was to the wrong branch, you may
git checkout theRightBranch
with all the changes stages. As I just had to do. – Frank Shearar Oct 5 '10 at 15:44535
If you're working in DOS, instead of
git reset --soft HEAD^
you'll need to usegit reset --soft HEAD~1
. The ^ is a continuation character in DOS so it won't work properly. Also,--soft
is the default, so you can omit it if you like and just saygit reset HEAD~1
. – Ryan Lundy Apr 13 '11 at 14:15144
zsh users might get:
zsh: no matches found: HEAD^
– you need to escape ^ i.e.git reset --soft HEAD\^
– tnajdek Feb 21 '13 at 17:4717
The answer is not correct if, say by accident,
git commit -a
was issued when the-a
should have been left out. In which case, it's better no leave out the--soft
(which will result in--mixed
which is the default) and then you can restage the changes you meant to commit. – dmansfield Jul 2 '14 at 21:198
In more recent versions of git
HEAD~
can be replaced with@~
. – ThomasW Sep 16 '16 at 5:56