switching branches with uncommitted changes in git - git-stash

I am working on my master branch and have some uncommitted changes inside the master branch. I have already created a feature branch and I am able to switch to my feature branch using the git checkout feature_branch command. I have couple of doubts here which I am listing below:
Why am I seeing the uncommitted changes in my branch when I have made my changes inside my master branch. If I commit my changes in the master branch and switch to my feature branch, I do not see the committed changes specific to master. I am expecting the same behavior for uncommitted changes also.
I came across the stash command in Git and there it was mentioned that if you have any uncommitted changes inside the master branch, and would like to switch to some other branch, git will not allow you and hence you need to stash the changes inside the master branch and then only switch to the development branch. I did not face this issue. Am I missing something here and if so, what is the significance of using the stash command?

If I commit my changes in the master branch and switch to my feature branch, I do not see the committed changes specific to master. I am expecting the same behavior for uncommitted changes also.
That's not a sensible behavior. Uncommitted changes are by definition not made to a branch. Branches are pointers to commits, and there is no commit associated with uncommitted changes. They are made to your working directory and have nothing tying them to any branch. They aren't even associated with Git. Until you commit (or stash) them, Git does absolutely nothing to track them, and it will never try to manage them for you.
I came across the stash command in Git and there it was mentioned that if you have any uncommitted changes inside the master branch, and would like to switch to some other branch, git will not allow you and hence you need to stash the changes inside the master branch ...
That's wrong. Stashes don't exist inside any branch. There is one global pool of stashes.
... I did not face this issue.
You will only be prevented from switching branches if doing so would cause your uncommitted changes to be overwritten.
Am I missing something here and if so, what is the significance of using the stash command?
You only need to worry about stashing your changes if they affect any files that would be changed by switching branches. If you have modifications to a file that is identical between two branches, switch from one branch to the other will not require a stash. If the file is different on your other branch, Git will not let you switch branches, as this would destroy your uncomitted changes.
It is safe to try switching branches, and if Git warns you that "uncommitted changes would be overwritten" and refuses to switch branches, you can stash your changes and try again.

Related

Are commits preserved by GitLab even after the branch is deleted after MR get merged

In our development using GitLab we usually squash commits from feature branches when they are merged in main branch (we use rebase strategy instead of merge if it matters).
But if the commits from feature branch are squashed to a single commit (which is later merged in main branch) and the branch itself is deleted, how can GitLab still show the original commits? Are they kept in the repository forever or it is a matter of time when they finally get dropped?
I believe GitLab does some garbage collection on the repository, but I wonder why it does not affect commits from MR.
The squash and merge commit page does mention:
Each time a branch merges into your base branch, up to two commits are added:
The single commit created by squashing the commits from the branch.
A merge commit, unless you have enabled fast-forward merges in your project.
Fast-forward merges disable merge commits
That merge commit might very well keep a reference to the branch before squashing, which can explain why the original commits are still visible.
If that is not the case, meaning nothing actually references those commits, then housekeeping (described here for self-managed GitLab, but also active on Cloud offering) will remove them the repository eventually.
However:
Gitaly cannot ever delete unreachable objects from object pools because they might be used by any of the forks that are connected to it.
Gitaly must keep all objects reachable due to the same reason. Object pools thus maintain references to unreachable “dangling” objects so that they don’t ever get deleted.
In case of squashing, the feature branch commits are squashed into a single commit to be pushed to the target branch. On the target branch, you will see only a single commit.
See this image to see the commit on the target branch i.e. vighnesh_develop
But you will still be able to see the individual commits on the merge request from the deleted feature branch. The feature branch is deleted but all the merge requests are maintained for lifetime unless we manually set an expiration period.
See this merge request for squashed commit
Hence, the individual commits are linked to the merge requests and not to the deleted branch or the target branch. Git will maintain a list of ALL the commits even though the branch from which the commit came is deleted. That is how it is able to do effective version control.

Creating a Merge Request via GitLab GUI: why is there always "1 commit behind the target branch"?

As in the title: there's always the statement The source branch is 1 commit behind the target branch. How is it even possible: both master and develop branches are up to date, no one made any modifications in the meantime, and the merge request gets created via GUI operating on the most up to date version of the repository, isn't it?
I read GitLab documentation saying that it could be the merge commit counted as this 1 commit behind, so I changed my project settings to:
It didn't change anything however: there's still the same message:
So far, I make a rebase in the following way:
git checkout master
git pull
git checkout develop
git merge master
git push
to line up the branches, but I'd like to save myself these few additional steps. Is it possible to achieve?

Setup GitLab Pipeline

I need to set up a pipeline for a branch that will do the following,
On push, it will trigger a pipeline (which happens as per GitLab)
1st Job to trigger a build (.net5) for the branch (new code pushed to the branch). If the build succeeds, it will begin the next job. However, I am to trigger build (MSBuild) on the runner location check out when the pipeline runs. But is there any way to directly run a build on the branch?
If the above build fails, the push should be reverted on a branch. I applied git revert and reset commands, but it only gets used to the build location of the runner. I need to revert commit at the branch level.
When GitLab starts a pipeline, it is a "detached HEAD" which basically means it creates a temporary branch that points to your specific commit. It does this because there might be a commit after it which the current build doesn't know about.
To get out of the detached head, you need to switch to the branch directly.
git checkout branch-name
To get the branch name, you find an appropriate predefined variable which works for your.
Once you have that, you need to get the latest version so you can revert. I usually needed the reset here to make things work.
git reset --hard
git pull
From there, you can revert. Now, the CI process doesn't have write permissions, so you need to have a GitLab access token with write permissions, which means you have to set up a new origin or parent.
git remote add changes https://oauth2:$PUSH_GITLAB_TOKEN#gitlab.com/group-name/project-1
git push -f changes branch-name
Now... that said, this is probably not what you want to do. Since you said you were new to CI, I'm going to say I'm 99.99999% sure you don't want to go down this path because it only leaves to heartache and frustration.
The reason is the branch may have a second or additional commit. It could be you missed something at the last minute and threw up a new one, an automated process starts up, or just your typical race conditions. Reverting a commit means you either will blow up with those changes or you end up erasing every other commit as you have to force push to get it up.
This also means that this is a very fragile process and will break many times, usually at the worst times (when you have a rapid series of commits), and then you have to tell everyone to stop working while you fix it.
(A good sign is how much work you have to do to fight the CI process.)
Instead, I recommend you create a merge request (MR) against your branch and set up the rules to make sure that is valid before you merge it into your branch. That way, the process doesn't have to worry about future or past commits, it just says what you have in your merge request (which is another branch) can't be applied after merging it with branch-name.
In our team, we have many branches (main, next, release/2.3.4, release/2.4.0, etc.) and doing MRs against each one has worked out well. We do the merge requests against each of the release branches, and the CI process says it can merge and pass tests before it tries to commit, but then we can commit knowing that 98+% of the time, it will be fine.
And it doesn't require jumping through hoops.

Do i have to commit my bitbucket-pipelines.yml each time make a change?

I want to test my pipeline and not have a commit everytime i make a change. Is there a way to prevent this, in order not to have a bunch of unnecessary commits on my develop branch?
You can use git commit --amend to push the commit into the previous one, this will trigger the pipeline to run with the new changes without "bloating" your git history with many commits.
Here is a tutorial to help you out: https://www.atlassian.com/git/tutorials/rewriting-history

How To Pull Latest Files from Dev Branch and NOT master?

I'm new to Git and I'm really confused here. I have a HTTPS from my github, and I am using terminal from a virtual box to try to pull the latest files from one of my branches.
Everytime I use the following command:
git pull http-link or git clone http-link
it only pulls the files from the master branch, and not ALL the branches. I know this because when I run git branch I only see the master branch, and not the develop branch that I have in github. I want the files from this develop branch (NOT master) so I can push the changes to that branch, before merging to master. Please advise.
it only pulls the files from the master branch, and not ALL the branches
The rules for pull are somewhat configuration-dependent, but I can tell you that when you clone it is getting the entire history (all branches) unless you give it specific options telling it not to (such as --single-branch).
I know this because when I run git branch I only see the master branch
That's because by default git branch lists the local branches, and not every known branch from the remote(s). You can say
git branch -a
to see the rest. They'll appear with names like
remotes/origin/branch-name
because what you have are not proper branches; rather these are sort of "bookmarks" that tell you where the remotes branches were, when last you fetched from the remote.
By default, cloning does not automatically create local branches for every branch on the remote (but it does fetch the branches). By default cloning does check out the default branch from the remote (master in this case), creating the local branch for it. And there are shortcuts built in to git such that, in a typical configuration with a single remote, you can say
git checkout branch-name
to create the local branch corresponding to the remote's branch-name branch.
Note that when you do this initial checkout, you don't want to say
git checkout remotes/origin/branch-name
because that does something else. Rather than create the local branch, this simply puts you in "detached HEAD" state, with HEAD on the same commit as the remote branch.

Resources