When to unbind and rebind vaos?

I am very new to open gl and am struggling to understand relation between vaos vbos and ibos
like how is currently bound vao related to currently bound ibo?

now i am trying to render 4 triangles with vertex data and index data for ibo as

float vertices[] = {
        -0.5f, -0.5f,  2.0f,     1.0f, 0.0f, 0.0f ,1.0,
         0.5f, -0.5f,  2.0f,     0.0f, 1.0f, 0.0f ,1.0,
         0.0f,  0.5f,  2.0f,     0.0f, 0.0f, 1.0f ,1.0,

         0.0f,  0.0f,  1.0f,     1.0f, 1.0f, 0.0f ,1.0,
         0.0f,  0.0f,  3.0f,     0.0f, 1.0f, 1.0f ,1.0,
         0.0f, -1.0f,  2.0f,     1.0f, 0.0f, 1.0f ,1.0,
    };

    float vertices1[] = {
        -0.5f, -0.5f,  0.0f,     1.0f, 0.0f, 0.0f ,1.0,
         0.5f, -0.5f,  0.0f,     0.0f, 1.0f, 0.0f ,1.0,
         0.0f,  0.5f,  0.0f,     0.0f, 0.0f, 1.0f ,1.0,

         0.0f,  0.0f, -1.0f,     1.0f, 1.0f, 0.0f ,1.0,
         0.0f,  0.0f,  1.0f,     0.0f, 1.0f, 1.0f ,1.0,
         0.0f, -1.0f,  0.0f,     1.0f, 0.0f, 1.0f ,1.0
    };
            
    unsigned indices[] = {
        0,1,2,3,4,5
    };

    unsigned indices1[] = {
         0,1,
         1,2,
         2,0,
         3,4,
         4,5,
         5,3
    };

and i am creating vaos and ibos as:

unsigned int VBO[2], VAO[2], IBO[2];
    glGenVertexArrays(2, VAO);
    glGenBuffers(2, VBO);
    glGenBuffers(2, IBO);
    glBindVertexArray(VAO[0]);

    glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO[0]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);
   
    glBindVertexArray(0);
    //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);



    glBindVertexArray(VAO[1]);

    glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices1), vertices1, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO[1]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices1), indices1, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);
    
    glBindVertexArray(0);
    //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

And I am drawing it as:

Lcall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO[0]));
        GLcall(glBindVertexArray(VAO[0]));

        GLcall(glDrawElements(GL_TRIANGLES, sizeof(indices1) / sizeof(unsigned), GL_UNSIGNED_INT, 0));

        GLcall(glBindVertexArray(0));
        //GLcall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));


        GLcall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO[1]));
        GLcall(glBindVertexArray(VAO[1]));

        GLcall(glDrawElements(GL_LINES, sizeof(indices1)/sizeof(unsigned), GL_UNSIGNED_INT, 0));

        GLcall(glBindVertexArray(0));
        //GLcall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));

now my question is that if i dont unbind vao in the draw call then it will not be drawn as expected like partially drawn lines or entirely not drawn triangles.
Are’nt vaos supposed to override any previous bindings and bind a new one specified?
Even if i dont unbind vao after setting glVertexAttribPointer I get a blank screen! Then I got Totally confused on when to bind before doing what.
What does vao hold other than vertex attribute?

ps: GLcall is a macro to check for errors after each opengl function.

The GL_ELEMENT_ARRAY_BUFFER binding is stored in a VAO. Changing the binding with glBindBuffer changes the value stored in the currently VAO (in 4.5 and later, you can use glVertexArrayElementBuffer to change the element buffer for a specific VAO). The behaviour of changing the binding with no VAO bound appears to be unspecified. Draw calls which use an element buffer (glDrawElements etc) use the buffer stored in the current VAO.

A VAO also stores the VBO associated with each attribute array. The current GL_ARRAY_BUFFER binding is context state (not stored in a VAO). Each call to glVertexAttribPointer stores the buffer bound to GL_ARRAY_BUFFER at the time of the call along with the parameters.

You don’t need the glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,...) calls in the drawing code. The element buffer is stored in the VAO.

If you remove the first glBindVertexArray(0) call but keep the subsequent glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,IBO[1]) call, this will make IBO[1] the element buffer for VAO[0] (because that will be the current VAO at that point).

It also stores the GL_ELEMENT_ARRAY_BUFFER binding.