Git Branches | just the twig *

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 -f

The second option for me did not run: I had to do git push -f master to restore the remote repository too. However, be aware that with the -f switch the commits after the restored commit are also LOST on the remote repo! (this is what I wanted but someone else may wish to preserve history).

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:

When you can undo changes

In the standard Git workflow:

  1. You create or edit a file. It starts in the unstaged state. If it’s new, it is not yet tracked by Git.
  2. You add the file to your local repository (git add), which puts the file into the staged state.
  3. You commit the file to your local repository (git commit).
  4. 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:

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.

  1. Confirm that the file is unstaged (that you did not use git add <file>) by running git 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")
    
  2. 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.

  1. Confirm that the file is staged (that you used git add <file>) by running git 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>
    
  2. 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.

  1. From the branch where you want to save your work, type git stash.

  2. Swap to another branch (git checkout <branchname>).

  3. Commit, push, and test.

  4. Return to the branch where you want to resume your changes.

  5. Use git stash list to list all previously stashed commits.

  6. 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.

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.

  1. Find the commit SHA of the commit you want to revert to. To look through a log of commits, type git log.

  2. 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:

  1. Check out the last correct commit. In this example, B.

    git checkout <commit-B-SHA>
    
  2. Create a new branch.

    git checkout -b new-path-of-feature
    
  3. 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 commit B, but you leave default pick 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 commit B, but leave default pick 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.

Use revert to keep branch flowing
Use revert to keep branch flowing
[Gbuy id=’147669′]

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.

Modifying history causes problems on remote branch
Modifying history causes problems on remote branch
[Gbuy id=’147670′]

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

 


Cloning / BranchesBranches - OverviewHARD^ Soft Revert

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.

Git Tutorial: git 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:

Git Tutorial: repository without any branches

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:

Git Tutorial: Create new branch

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.

Get started now

 

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 GitHub repository for git reset and push example

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.

Performing a git reset and push to remote on GitHub

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.


 

 

 

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.

  1. If the developer wants to merge master into a branch that’s protected, they must perform a GitLab merge request.
  2. 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.

gitlab delete remote branch

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:

  1. Open a Terminal window on the client machine
  2. Switch to the feature branch
  3. Use git to merge master into the branch
  4. View a directory listing to validate files from master have been moved to the feature branch
  5. View the Git reflog to validate that a master merge commit is registered
  6. Push the merged feature branch back to the GitLab server
  7. 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.

gitlab master 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 GitHub repository for git reset and push example

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.

Performing a git reset and push to remote on GitHub

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.


 

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

  1. Edit file again ‘edit_this_file.rb’
  2. Check status
  3. Add and commit with wrong message
  4. Check log
  5. Amend commit
  6. Check log
  7. Soft reset
  8. Check log
  9. Pull for updates
  10. 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 vs git 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)
  1. 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).
  2. Make corrections to working tree files.
  3. git add anything that you want to include in your new commit.
  4. 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.

 

Share

Improve this answer

Follow

edited Dec 21 '20 at 16:53

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:44

  • 535

    If you're working in DOS, instead of git reset --soft HEAD^ you'll need to use git 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 say git reset HEAD~1. – Ryan Lundy Apr 13 '11 at 14:15

  • 144

    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:47

  • 17

    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:19

  • 8

    In more recent versions of git HEAD~ can be replaced with @~. – ThomasW Sep 16 '16 at 5:56

Show 11 more comments

Scroll to Top